73 votes

Est-ce que NULL est toujours faux ?

Est-il sûr de supposer que NULL se traduit toujours par faux en C?

void *somePtr = NULL;

if (!somePtr) {
  /* Cela sera-t-il toujours exécuté? */
}

Ou devrait-on faire une vérification explicite de la valeur de NULL?

0 votes

Je vous renvoie simplement à Question 5.3 du C-FAQ. Elle répond à cette question précise.

0 votes

Votre code n'utilise pas la valeur si NULL

77voto

tvanfosson Points 268301

Oui. NULL évalue à faux, car en C, toute valeur non nulle est considérée comme vraie et toute valeur nulle est considérée comme fausse. NULL est essentiellement l'adresse de zéro et est traitée comme telle dans les comparaisons, et je crois qu'elle serait convertie en un entier pour la vérification booléenne. Je m'attends à ce que votre code soit lisible par toute personne familière avec le langage C, bien que je ferais probablement la vérification de manière explicite.

En programmation C et C++, deux pointeurs nuls sont garantis de comparer égaux ; ANSI C garantit que tout pointeur nul sera égal à 0 dans une comparaison avec un type entier ; en outre, la macro NULL est définie comme une constante de pointeur nul, c'est-à-dire la valeur 0 (soit en tant que type entier, soit convertie en un pointeur vers void), donc un pointeur nul sera égal à NULL.

Réf : http://en.wikipedia.org/wiki/Null_pointer#Null_pointer

4 votes

Une vérification explicite peut être plus claire dans certains cas, mais c'est un idiome C qui est garanti par le langage d'être valide. :)

2 votes

J'aurais pleuré si tout mon code C utilisant ces if était maintenant invalide :)

0 votes

La norme n'est pas très claire sur la question : il est garanti que 0 converti en un type de pointeur sera un pointeur nul, mais à ma connaissance cela ne spécifie pas ce qui se passera lorsqu'un pointeur nul est converti en int!

20voto

Hans Passant Points 475940

Le langage 'C' date d'une époque où (void*)0 pouvait réellement être un pointeur valide. Ce n'est pas si loin, les microprocesseurs 8080 et Z80 avaient un vecteur d'interruption à l'adresse 0. Face à de telles choix d'architecture, il ne pouvait rien faire d'autre que de laisser un fichier d'en-tête déclarer la valeur de NULL. Il y avait des compilateurs, aujourd'hui oubliés, où NULL n'était pas égal à (void*)0 (0xffff était la prochaine alternative), ce qui donnait à votre instruction if() un comportement indéfini.

Heureusement, C++ a mis fin à cela, un pointeur nul est affectable à 0 et testable contre 0.

0 votes

Les unités de gestion de la mémoire (MMU) étaient probablement plus importantes que le C++ dans le changement.

1 votes

Au sujet de votre phrase en C++ : c'est incorrect. 0 n'est pas un pointeur nul. 0 est une constante de pointeur nul. void *p = 0; maintenant, p est un pointeur nul. C'est une différence, car un pointeur nul a un type de pointeur, tandis qu'une constante de pointeur nul a un type entier et est une expression constante

2 votes

C99 garantit que 0 converti en un type de pointeur sera également un pointeur nul - je ne me suis jamais soucié de lire les normes précédentes, donc je n'ai aucune idée de quand cela s'est produit...

19voto

akatakritos Points 5164

Il n'est jamais sûr de supposer quoi que ce soit.

Une vérification explicite est également plus claire sur ce que vous testez.

0 votes

Nous avions l'habitude d'aller plus loin en définissant une valeur nulle spécifique au type pour chacun de nos éléments typedef'ed : structs, int, longs, peu importe. De cette façon, la condition serait "if (foo != fooNil) { etc. }". Avertissement : J'avais l'habitude de travailler pour Simonyi chez Xerox, donc mon cerveau était contaminé.

1 votes

@Peter Rowell : pendant longtemps, j'ai utilisé #define NIL(x) ((x)0) pour obtenir approximativement cet effet : NIL(foo), NIL(char *), NIL(bar), etc.

1 votes

@Jonathan: dans quelle langue - C ou C++? En C99, c'est inutile, car "Tout couple de pointeurs nuls doit être comparable."

14voto

Captain Segfault Points 1106

Oui (du moins pour tout compilateur C conforme aux normes!)

De la FAQ comp.lang.c:

Q: Est-il valide d'utiliser la comparaison abrégée des pointeurs ``if(p)'' pour tester les pointeurs non nuls? Et si la représentation interne des pointeurs nuls est non nulle?

R: C'est toujours valide.

3voto

Brendan Dowling Points 374

NULL n'est qu'une définition de préprocesseur. Il se trouve dans stdio.h. En général, seule une personne folle le redéfinirait, mais c'est possible. Un exemple :

#include 
#ifdef NULL
#undef NULL
#endif
#define NULL 1

void main()
{

        if (NULL)
                printf("NULL is true\n");
        else
                printf("NULL is false\n");
}

Ce code affichera "NULL est vrai". Essayez-le si vous ne me croyez pas. Votre compilateur pourrait même ne pas vous avertir que vous faites quelque chose d'étrange.

1 votes

Mais si vous définissez NULL à 1 et assignez somePtr = NULL, vous obtiendrez au moins un avertissement que vous convertissez un entier en pointeur.

0 votes

Intéressant. Vous pouvez le rendre non averti en faisant: #define NULL (void *) 1

3 votes

Ce serait tout simplement faux. Le compilateur et la bibliothèque standard C sont regroupés pour une raison. Si vous y touchez, vous cassez cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X