web-dev-qa-db-fra.com

C: Comparaison avec NULL

Arguments religieux mis à part:

  • Option 1:

    if (pointer[i] == NULL) ...
    
  • Option 2:

    if (!pointer[i]) ...  
    

En C, l’option 1 est-elle fonctionnellement équivalente à l’option 2? 

La résolution ultérieure est-elle plus rapide en raison de l'absence de comparaison?

21
Ande TURNER

J'aime le second, les autres aiment le premier.

En fait, je préfère un troisième type au premier:

if (NULL == ptr) {
   ...
}

Parce qu'alors je:

  • ne sera pas en mesure de manquer et tapez simplement un "="
  • ne manquez pas le "== NULL" et confondez-le avec le contraire si la condition est longue (plusieurs lignes)

Fonctionnellement, ils sont équivalents.

Même si un pointeur NULL n'est pas "0" (tous les bits nuls), if (!ptr) est comparé au pointeur NULL.

Ce qui suit est incorrect. Il est toujours là car de nombreux commentaires y font référence: Ne comparez pas un pointeur avec un zéro littéral, cependant. Cela fonctionnera presque partout mais c'est un comportement non défini IIRC.

15
Thomas

Je préfère le style explicite (première version). Il est évident qu’il s’agit d’un pointeur et non d’un nombre entier ou autre, mais d’une question de style. 

Du point de vue de la performance, cela ne devrait faire aucune différence. 

33
Laserallan

Équivalent. C'est ce que dit la norme de langue. Et les gens ont les damndest préférences religieuses!

30
Norman Ramsey

Il est souvent utile de supposer que les auteurs de compilateur ont au moins un minimum d'intelligence. Votre compilateur est not écrit par des canetons commotionnés. Il est écrit par des êtres humains, avec des années d'expérience en programmation et des années consacrées à l'étude de la théorie des compilateurs. Cela ne veut pas dire que votre compilateur est parfait et sait toujours mieux, mais cela signifie que [] est parfaitement capable de gérer des optimisations automatiques triviales.

Si les deux formes sont équivalentes, alors pourquoi le compilateur ne traduirait-il pas l'une dans l'autre pour s'assurer que les deux sont d'une efficacité équivalente?

Si if (pointer[i] == NULL) était plus lent que if (!pointer[i]), le compilateur ne le changerait-il pas simplement dans le deuxième formulaire, plus efficace?

Donc non, à supposer qu'ils soient équivalents, ils sont tout aussi efficaces.

Quant à la première partie de la question, oui, elles sont équivalentes. En fait, le standard de langage l'indique explicitement quelque part - un pointeur vaut true s'il n'est pas NULL et false s'il est NULL, les deux sont donc exactement identiques.

19
jalf

Presque certainement aucune différence de performance. Je préfère le style implicite de la seconde, cependant.

9
Barry Kelly

NULL doit être déclaré dans l'un des fichiers d'en-tête standard en tant que tel:

#define NULL ((void*)0)

Donc, dans les deux cas, vous comparez à zéro et le compilateur doit optimiser les deux de la même manière. Chaque processeur a une "optimisation" ou un opcode permettant de comparer avec zéro.

3
Mark Rushakoff

L'optimisation précoce est mauvaise. La micro-optimisation est également mauvaise, sauf si vous essayez d'extraire le dernier bit en Hz de votre processeur, il est inutile de le faire. Comme les gens l'ont déjà montré, le compilateur optimisera de toute façon l'essentiel de votre code.

Il est préférable de rendre votre code aussi concis et lisible que possible. Si cela est plus lisible

if (!ptr)

que cela

if (NULL==ptr)

puis l'utiliser. Tant que tous ceux qui liront votre code seront d’accord. 

Personnellement, j'utilise la valeur entièrement définie (NULL == ptr), de sorte qu'il est clair ce que je recherche. Peut-être plus long à taper, mais je peux facilement le lire. Je pense que le! Ptr serait facile à manquer! si vous lisez trop vite.

1
shimpossible

Cela dépend vraiment du compilateur. Je serais surpris que la plupart des compilateurs C modernes ne génèrent pas du code pratiquement identique pour le scénario spécifique que vous décrivez.

Demandez à votre compilateur de générer une liste Assembly pour chacun de ces scénarios et répondez à votre propre question (pour votre compilateur particulier :)).

Et même s'ils sont différents, la différence de performance ne sera probablement pas pertinente dans les applications pratiques.

0
Thomas Lee

Activer l'optimisation du compilateur et ils sont fondamentalement les mêmes

testé sur gcc 4.3.3

int main (int argc, char** argv) {
   char c = getchar();
   int x = (c == 'x');
   if(x == NULL)
      putchar('y');
   return 0;
}

contre

int main (int argc, char** argv) {
   char c = getchar();
   int x = (c == 'x');
   if(!x)
      putchar('y');
   return 0;
}


gcc -O -o test1 test1.c
gcc -O -o test2 test2.c


diff test1 test2

produit pas de sortie :)

0
Charles Ma