C: Comparaison de la valeur NULL
Arguments religieux de côté:
-
Option1:
if (pointer[i] == NULL) ...
-
Option2:
if (!pointer[i]) ...
En C est option1 fonctionnellement équivalent à option2?
Le plus tard résoudre plus rapidement en raison de l'absence d'une comparaison ?
- Est-il sûr de supposer que le "pointeur" est en fait un tableau de pointeurs? Elle pourrait rendre la question plus claire si vous retirez le "[i]".
- Sudo, vous avez besoin pour se détendre. Vous êtes à hurler à jalf.com pour une réponse honnête. Le fait que vous êtes à même de demander: "ces ont des performances équivalentes" ou encore "ce sont les mêmes" démontre que vous avez besoin d'ouvrir votre esprit et ne pas assumer tout est une attaque.
Vous devez vous connecter pour publier un commentaire.
J'aime bien le deuxième, d'autres personnes comme la première.
En fait, je préfère un troisième à la première:
Parce que je:
Fonctionnellement, ils sont équivalents.
Même si un
NULL
pointeur n'est pas "0" (zéro tous les bits),if (!ptr)
compare avec laNULL
pointeur.Le suivant est incorrect. Il est toujours là parce qu'il y a de nombreux commentaires se référant à elle:
Ne comparez pas un pointeur avec littérale zéro, cependant. Il travaillera presque partout, mais est un comportement indéfini IIRC.
(void*)0
est de trop, en C. Lorsqu'ils sont convertis en un type pointeur, il devient une valeur de pointeur null. C'est quand il devient un pointeur pointant vers une adresse pas égale à 0x0. Mais cela n'a rien à voir avec la comparaison d'un pointeur à 0. Ce n'est pas comparable à l'adresse 0. Un entier n'est pas une adresse.NULL
n'est pas0
mais plutôt(void*) 0
- je ne sais pas, si cela fait une réelle différence.Je préfère l'explicite style (première version). Il est clair qu'il y a un pointeur impliquées et non un entier ou d'autre chose, mais c'est juste une question de style.
À partir d'un point de vue des performances, il devrait pas faire de différence.
Équivalent. Il le dit dans la langue standard. Et les gens ont le damndest préférences religieuses!
Il est souvent utile de supposer que les rédacteurs du compilateur ont au moins un minimum d'intelligence. Votre compilateur est pas écrit par subi une commotion canetons. Il est écrit par des êtres humains, avec des années d'expérience de la programmation, et les années passées à étudier la théorie des compilateurs. Cela ne signifie pas que votre compilateur est parfait, et toujours connaît le mieux, mais il ne dire qu'il est parfaitement capable de gérer trivial optimisation automatique.
Si les deux formes sont équivalentes, alors pourquoi ne pas le compilateur juste traduire l'une dans l'autre pour assurer les deux sont tout aussi efficaces?
Si
if (pointer[i] == NULL)
a été plus lent queif (!pointer[i])
, ne serait pas le compilateur, il suffit de changer dans le second, forme plus efficace?Donc pas, en supposant qu'ils sont équivalents, ils sont tout aussi efficaces.
Comme pour la première partie de la question, oui, ils sont équivalents. La langue standard en fait l'indique explicitement quelque part, un pointeur prend la valeur true si elle est non NULLE, et false si elle est NULLE, de sorte que les deux sont exactement identiques.
Presque certainement aucune différence dans les performances. Je préfère le style implicite de la seconde, si.
NULL
doit être déclaré dans l'un des fichiers d'en-tête standard en tant que tel:Donc de toute façon, vous comparez par rapport à zéro, et le compilateur d'optimiser à la fois la même façon. Chaque processeur a une certaine "optimisation" ou de l'opcode pour comparer avec zéro.
#define NULL (void *)0
.NULL
être définie comme0
.Début de l'optimisation est mauvais. Micro optimisation est également mauvais, sauf si vous essayez de serrer chaque dernier peu de Hz à partir de votre CPU, il n'y a aucun point à elle de le faire. Comme les gens l'ont déjà montré, le compilateur d'optimiser le plus de votre code à l'écart de toute façon.
De son mieux pour rendre votre code plus concis et lisible que possible. Si c'est plus lisible
que ce
ensuite de l'utiliser. Tant que tout le monde qui va lire votre code est d'accord.
Personnellement, j'utilise le entièrement défini la valeur (NULL==ptr) il est évident que je vérifie pour. Peut être plus long à taper, mais je peux facilement lire. Je pense à la !ptr serait facile de manquer ! si la lecture rapidement.
Cela dépend vraiment sur le compilateur. Je serais surpris si la plupart des modernes, les compilateurs C ne pas générer pratiquement identiques code pour le scénario que vous décrivez.
Obtenir votre compilateur pour générer une assemblée d'inscription pour chacun de ces scénarios et vous pouvez répondre à votre propre question (pour votre compilateur :)).
Et même si ils sont différents, la différence de performances sera probablement pas pertinente dans des applications pratiques.
Tour sur l'optimisation du compilateur et ils sont fondamentalement les mêmes
testé sur gcc 4.3.3
vs
produit aucune sortie 🙂
-O0
pour aucun des optimisations en effet, les résultats dans les différents fichiers binaires.J'ai fait un assemblage de vidage, et trouvé la différence entre les deux versions:
@@ -11,8 +11,7 @@
pushl %ecx
subl $20, %esp
movzbl -9(%ebp), %eax
- movsbl %al,%eax
- testl %eax, %eax
+ testb %al, %al
Il ressemble à ce dernier génère une instruction et le premier génère deux, mais c'est assez peu scientifique.
C'est gcc, pas d'optimisations:
test1.c:
test2.c: Changement
pointer[0] == NULL
à!pointer[0]
gcc-s test1.c, gcc-s test2.c, diff -u test1.s test2.s
char
àNULL
? La question était sur les pointeurs. (Peut-être que je suis en train de lire le démontage, le mal, n'hésitez pas à me frapper si c'est ainsi.)exit(1)
, la comparaison est optimisé complètement. Notez aussi que votre extrait de caractéristiques de comportement indéfini (l'accès à un objet non initialisé).Attention, gcc devrait avoir heurté un avertissement, si ce n'est le cas de la compilation avec
-Wall
drapeau surCependant, vous devriez toujours compiler à l'optimisation de gcc code.
BTW, faites précéder votre variable avec le mot clé volatile afin d'éviter la gcc à partir de l'ignorer...
De toujours mentionner votre compilateur version 🙂