Dans les premiers jours du C ++, quand il était boulonné sur C, vous ne pouviez pas utiliser NULL tel qu'il était défini comme (void*)0
. Vous ne pouviez pas affecter NULL à un pointeur autre que void*
, ce qui le rendait inutile. À l'époque, il était admis que vous utilisiez 0
(zéro) pour les pointeurs nuls.
À ce jour, j'ai continué à utiliser zéro comme pointeur nul, mais ceux qui m'entourent insistent pour l'utiliser NULL
. Personnellement, je ne vois aucun avantage à donner un nom ( NULL
) à une valeur existante - et puisque j'aime aussi tester les pointeurs en tant que valeurs de vérité:
if (p && !q)
do_something();
alors utiliser zéro a plus de sens (comme si vous utilisez NULL
, vous ne pouvez pas logiquement utiliser p && !q
- vous devez comparer explicitement NULL
, sauf si vous supposez qu'il NULL
est zéro, auquel cas pourquoi utiliser NULL
).
Y a-t-il une raison objective de préférer zéro à NULL (ou vice versa), ou est-ce simplement une préférence personnelle?
Edit: Je devrais ajouter (et je voulais dire à l'origine) qu'avec RAII et les exceptions, j'utilise rarement des pointeurs zéro / NULL, mais parfois vous en avez encore besoin.
Réponses:
Voici le point de vue de Stroustrup à ce sujet: FAQ sur le style et la technique C ++
Cela dit, ne vous inquiétez pas pour les petites choses.
la source
Il y a quelques arguments (dont l'un est relativement récent) qui, je crois, contredisent la position de Bjarne à ce sujet.
L'utilisation
NULL
permet d'effectuer des recherches sur son utilisation et met également en évidence le fait que le développeur voulait utiliser unNULL
pointeur, qu'il soit interprété par le compilateur commeNULL
ou non.L'exemple que tout le monde cite est:
void foo(int*); void foo (int); void bar() { foo (NULL); // Calls 'foo(int)' }
Cependant, au moins à mon avis, le problème avec ce qui précède n'est pas que nous utilisons NULL pour la constante de pointeur nul, c'est que nous avons des surcharges de «foo» qui prennent des types d'arguments très différents. Le paramètre doit également être un
int
, car tout autre type entraînera un appel ambigu et générera ainsi un avertissement utile du compilateur.Même en l'absence de C ++ 0x, il existe aujourd'hui des outils disponibles qui vérifient qu'il
NULL
est utilisé pour les pointeurs et qui0
est utilisé pour les types intégraux.std::nullptr_t
type.C'est le dernier argument de la table. Le problème de
0
etNULL
est activement résolu pour C ++ 0x, et vous pouvez garantir que pour chaque implémentation qui fournitNULL
, la toute première chose qu'ils feront est:#define NULL nullptr
Pour ceux qui utilisent
NULL
plutôt que0
, le changement sera une amélioration de type sécurité avec peu ou pas d' effort - si quoi que ce soit , il peut aussi attraper quelques bugs où ils ont utiliséNULL
pour0
. Pour quiconque utilise0
aujourd'hui ... euh ... eh bien j'espère qu'ils ont une bonne connaissance des expressions régulières ...la source
#include
et restez en sécurité jusqu'au bout.#define NULL nullptr
semble dangereux. Pour le meilleur ou pour le pire, beaucoup de code hérité utilise NULL pour des choses autres que 0. Par exemple, les descripteurs sont souvent implémentés comme un type intégral et leur définitionNULL
n'est pas rare. J'ai même vu des abus comme utiliserNULL
pour définir unchar
sur un terminateur zéro.NULL
sont en fait incorrectes. De nombreuses API sont utilisées depuis longtempsNULL
avec des descripteurs, et c'est en fait l'utilisation documentée avec beaucoup d'entre elles. Il n'est pas pragmatique de les briser soudainement et de déclarer qu'ils le font mal.Utilisez NULL. NULL montre votre intention. Que ce soit 0 est un détail d'implémentation qui ne devrait pas avoir d'importance.
la source
J'utilise toujours:
NULL
pour les pointeurs'\0'
pour les caractères0.0
pour flotteurs et doublesoù 0 ferait bien. Il s'agit de signaler l'intention. Cela dit, je ne suis pas anal à ce sujet.
la source
J'ai arrêté d'utiliser NULL au profit de 0 il y a longtemps (ainsi que la plupart des autres macros). Je l'ai fait non seulement parce que je voulais éviter les macros autant que possible, mais aussi parce que NULL semble être devenu sur-utilisé dans le code C et C ++. Il semble être utilisé chaque fois qu'une valeur 0 est nécessaire, pas seulement pour les pointeurs.
Sur les nouveaux projets, je mets ceci dans un en-tête de projet:
static const int nullptr = 0;
Maintenant, lorsque les compilateurs compatibles C ++ 0x arrivent, tout ce que j'ai à faire est de supprimer cette ligne. Un avantage appréciable de ceci est que Visual Studio reconnaît déjà nullptr en tant que mot clé et le met en évidence de manière appropriée.
la source
NULL
c'est surutilisé, je l'ai vu utilisé pour faire référence au caractère de terminaison zéro dans une chaîne! Je ne pense pas que cela justifie de l'éviter complètement.cerr << sizeof(0) << endl; cerr << sizeof(NULL) << endl; cerr << sizeof(void*) << endl; ============ On a 64-bit gcc RHEL platform you get: 4 8 8 ================
La morale de l'histoire. Vous devez utiliser NULL lorsque vous traitez avec des pointeurs.
1) Il déclare votre intention (ne me faites pas rechercher dans tout votre code en essayant de déterminer si une variable est un pointeur ou un type numérique).
2) Dans certains appels d'API qui attendent des arguments variables, ils utiliseront un pointeur NULL pour indiquer la fin de la liste d'arguments. Dans ce cas, l'utilisation d'un '0' au lieu de NULL peut poser des problèmes. Sur une plate-forme 64 bits, l'appel va_arg veut un pointeur 64 bits, mais vous ne passerez qu'un entier 32 bits. Il me semble que vous comptez sur les autres 32 bits pour être mis à zéro pour vous? J'ai vu certains compilateurs (par exemple l'icpc d'Intel) qui ne sont pas si gracieux - et cela a entraîné des erreurs d'exécution.
la source
NULL
n'est peut-être pas portable et n'est pas sûr. Il peut y avoir des plates-formes qui restent#define NULL 0
(selon la FAQ de Stroustrup: Dois-je utiliser NULL ou 0? Cité par la question principale et c'est parmi les premiers résultats de recherche). Au moins dans l'ancien C ++,0
a une signification conceptuelle particulière dans le contexte du pointeur. Vous ne devriez pas penser concrètement aux bits. Notez également que dans des contextes différents entiers (short
,int
,long long
) «sizeof(0)
» sera différent. Je pense que cette réponse est un peu erronée.NULL
place de(char *)0
,(const char *)0
ou(struct Boo *)0
ou(void *)0
ou quoi que ce soit pour exprimer plus clairement l'intention - sans être (à mon avis) trop encombrant.)Si je me souviens bien, NULL est défini différemment dans les en-têtes que j'ai utilisés. Pour C, il est défini comme (void *) 0, et pour C ++, il est défini comme juste 0. Le code ressemblait à quelque chose comme:
#ifndef __cplusplus #define NULL (void*)0 #else #define NULL 0 #endif
Personnellement, j'utilise toujours la valeur NULL pour représenter des pointeurs nuls, cela rend explicite le fait que vous utilisez un pointeur plutôt qu'un type intégral. Oui en interne, la valeur NULL est toujours 0 mais elle n'est pas représentée comme telle.
De plus, je ne compte pas sur la conversion automatique des entiers en valeurs booléennes, mais je les compare explicitement.
Par exemple, préférez utiliser:
if (pointer_value != NULL || integer_value == 0)
plutôt que:
if (pointer_value || !integer_value)
Autant dire que tout cela est résolu dans C ++ 11 où l'on peut simplement utiliser à la
nullptr
place deNULL
, etnullptr_t
c'est aussi le type de anullptr
.la source
Je dirais que l'histoire a parlé et que ceux qui ont plaidé en faveur de l'utilisation de 0 (zéro) se sont trompés (y compris Bjarne Stroustrup). Les arguments en faveur de 0 étaient principalement l'esthétique et la "préférence personnelle".
Après la création de C ++ 11, avec son nouveau type nullptr, certains compilateurs ont commencé à se plaindre (avec des paramètres par défaut) de passer 0 à des fonctions avec des arguments de pointeur, car 0 n'est pas un pointeur.
Si le code avait été écrit en utilisant NULL, une simple recherche et remplacement aurait pu être effectuée via la base de code pour le rendre nullptr à la place. Si vous êtes coincé avec du code écrit en utilisant le choix de 0 comme pointeur, il est beaucoup plus fastidieux de le mettre à jour.
Et si vous devez écrire un nouveau code maintenant selon la norme C ++ 03 (et que vous ne pouvez pas utiliser nullptr), vous devriez vraiment utiliser NULL. Cela vous facilitera grandement la mise à jour à l'avenir.
la source
J'utilise habituellement 0. Je n'aime pas les macros, et il n'y a aucune garantie qu'un en-tête tiers que vous utilisez ne redéfinit pas NULL pour être quelque chose d'étrange.
Vous pouvez utiliser un objet nullptr comme proposé par Scott Meyers et d'autres jusqu'à ce que C ++ obtienne un mot clé nullptr:
const // It is a const object... class nullptr_t { public: template<class T> operator T*() const // convertible to any type of null non-member pointer... { return 0; } template<class C, class T> operator T C::*() const // or any type of null member pointer... { return 0; } private: void operator&() const; // Can't take address of nullptr } nullptr = {};
Google "nullptr" pour plus d'informations.
la source
(void*)0
si elle est compilée en code C) ne demande que des problèmes et ne doit pas être utilisée.J'ai déjà travaillé sur une machine où 0 était une adresse valide et NULL était défini comme une valeur octale spéciale. Sur cette machine (0! = NULL), donc un code tel que
char *p; ... if (p) { ... }
ne fonctionnerait pas comme prévu. Tu as dû écrire
if (p != NULL) { ... }
Bien que je pense que la plupart des compilateurs définissent NULL comme 0 ces jours-ci, je me souviens encore de la leçon d'il y a des années: NULL n'est pas nécessairement 0.
la source
(void *)0
doit comparer égal àNULL
, mais ce n'est pas nécessairement le cas0
. Certaines personnes ont fait valoir queNULL
devrait être0xffffffff...
ou0xf7ffffff...
depuis0x00
peut être une adresse valide, mais jusqu'à présent, la plupart des implémentations utilisentNULL
=0
.0
selon la norme, c'est ce que vous écrivez dans votre code. Cependant, le compilateur peut choisir d'émettre une valeur différente pour la constante nulle dans le code machine résultant. En d'autres termes, lorsque vous écrivezp = 0;
(où p est un pointeur), le compilateur verra le0
comme la constante nulle. Mais lors de l'émission de l'instruction pour stocker "null", stockera la valeur nulle spécifique à la machine qui peut ou non être littéralement l'adresse0x0
.Je pense que la norme garantit que NULL == 0, vous pouvez donc faire l'un ou l'autre. Je préfère NULL car il documente votre intention.
la source
foo.bar_ptr = (Bar *) 0
exprime l'intention beaucoup plus clairement quefoo.bar_ptr = NULL
. Cette habitude permet également au compilateur de détecter les erreurs de conception erronée pour vous. Pour moi,foo.bar_ptr = 0
exprime l'intention ainsi que l'utilisationNULL
si je sais quefoo.bar_ptr
c'est un pointeur.L'utilisation de 0 ou de NULL aura le même effet.
Cependant, cela ne signifie pas qu'ils sont tous deux de bonnes pratiques de programmation. Étant donné qu'il n'y a pas de différence de performances, choisir une option de bas niveau par rapport à une alternative agnostique / abstraite est une mauvaise pratique de programmation. Aidez les lecteurs de votre code à comprendre votre processus de réflexion .
NULL, 0, 0.0, '\ 0', 0x00 et autres se traduisent tous par la même chose, mais sont des entités logiques différentes dans votre programme. Ils doivent être utilisés comme tels. NULL est un pointeur, 0 est une quantité, 0x0 est une valeur dont les bits sont intéressants, etc. Vous n'affecteriez pas '\ 0' à un pointeur qu'il compile ou non.
Je sais que certaines communautés encouragent la démonstration d'une connaissance approfondie d'un environnement en rompant les contrats de l'environnement. Les programmeurs responsables, cependant, créent un code maintenable et gardent ces pratiques hors de leur code.
la source
Étrange, personne, y compris Stroustroup, n'a mentionné cela. En parlant beaucoup de standards et d'esthétique, personne n'a remarqué qu'il est dangereux de l'utiliser
0
àNULL
la place de, par exemple, dans une liste d'arguments variables sur l'architecture oùsizeof(int) != sizeof(void*)
. Comme Stroustroup, je préfère0
pour des raisons esthétiques, mais il faut faire attention à ne pas l'utiliser là où son type pourrait être ambigu.la source
0
condition que vous spécifiez que0
vous voulez dire - par exemple(int *)0
,(char *)0
,(const char *)0
ou(void *)0
ou(unsigned long long) 0
ou autre. À mon avis, cela exprime l'intention beaucoup plus clairement queNULL
.NULL
signifie.(void *)
quand je pourrais utiliser le type exact. J'ai volontairement donné l'exemple d'un entier 64 bits (généralement) dans la liste car il est analogue au cas du pointeur. De plus, si je me souviens que l'ancien C ++ définiNULL
comme0
étant exact (cela fait des années que j'ai programmé en C ++), nous n'observons aucune amélioration de l'exactitude du programme. La nouvelle norme C ++ fournit heureusement unnullptr
mot-clé, nous pouvons donc nous débarrasser de cetteNULL
laideur et de toute la controverse lors de l'écriture de C ++ plus récent.(void*)
a été abstraitNULL
. EtNULL
exprime en fait l'intention assez clairement la plupart du temps. Et je pense que votre souvenir est faux. Je ne suis pas sûr des normes, mais en pratique, je pense que cela a été le cas(void*)0
. Et oui,nullptr
c'est un joli joli, bien que cela revienne au mêmeNULL
: spécifier un pointeur nul sans spécifier de type.nullptr
porte le même message queNULL
, c'était uniquement à propos de l'expression de l'intention que vous avez mentionnée au tout début. (PrétraitementNULL
surgcc
rendements modernes__null
, quels qu'ils soient).J'essaie d'éviter toute la question en utilisant des références C ++ lorsque cela est possible. Plutôt que
void foo(const Bar* pBar) { ... }
vous pourriez souvent être capable d'écrire
void foo(const Bar& bar) { ... }
Bien sûr, cela ne fonctionne pas toujours; mais les pointeurs nuls peuvent être surutilisés.
la source
Je suis avec Stroustrup sur celui-ci :-) Puisque NULL ne fait pas partie du langage, je préfère utiliser 0.
la source
Préférence principalement personnelle, bien que l'on puisse faire valoir que NULL montre clairement que l'objet est un pointeur qui ne pointe actuellement vers rien, par exemple
void *ptr = &something; /* lots o' code */ ptr = NULL; // more obvious that it's a pointer and not being used
IIRC, la norme n'exige pas que NULL soit égal à 0, donc utiliser ce qui est défini dans <stddef.h> est probablement le meilleur pour votre compilateur.
Une autre facette de l'argument est de savoir si vous devez utiliser des comparaisons logiques (conversion implicite en booléen) ou une vérification d'explicité par rapport à NULL, mais cela revient également à la lisibilité.
la source
Je préfère utiliser NULL car il indique clairement que votre intention est que la valeur représente un pointeur et non une valeur arithmétique. Le fait que ce soit une macro est malheureux, mais comme elle est si largement enracinée, il y a peu de danger (à moins que quelqu'un ne fasse quelque chose de vraiment stupide). J'aurais aimé que ce soit un mot-clé depuis le début, mais que pouvez-vous faire?
Cela dit, je n'ai aucun problème à utiliser les pointeurs comme valeurs de vérité en soi. Tout comme avec NULL, c'est un idiome enraciné.
C ++ 09 ajoutera la construction nullptr qui, je pense, est en retard depuis longtemps.
la source
J'utilise toujours 0. Pas pour une vraie raison réfléchie, juste parce que quand j'ai appris le C ++ pour la première fois, j'ai lu quelque chose qui recommandait d'utiliser 0 et je l'ai toujours fait de cette façon. En théorie, il pourrait y avoir un problème de confusion dans la lisibilité, mais en pratique, je n'ai jamais rencontré une seule fois un tel problème en milliers d'heures-homme et en millions de lignes de code. Comme le dit Stroustrup, ce n'est vraiment qu'un problème esthétique personnel jusqu'à ce que la norme devienne nullptr.
la source
Quelqu'un m'a dit une fois ... Je vais redéfinir NULL en 69. Depuis, je ne l'utilise plus: P
Cela rend votre code assez vulnérable.
Éditer:
Tout dans la norme n'est pas parfait. La macro NULL est une constante de pointeur NULL C ++ définie par l'implémentation qui n'est pas entièrement compatible avec la macro C NULL, ce qui, outre le type masquant implicite, la convertit en un outil inutile et sujet aux erreurs.
NULL ne se comporte pas comme un pointeur nul mais comme un littéral O / OL.
Dites-moi l'exemple suivant n'est pas déroutant:
void foo(char *); void foo(int); foo(NULL); // calls int version instead of pointer version!
C'est à cause de tout cela, dans le nouveau standard apparaît std :: nullptr_t
Si vous ne voulez pas attendre le nouveau standard et que vous voulez utiliser un nullptr, utilisez au moins un bon comme celui proposé par Meyers (voir le commentaire jon.h).
la source
NULL
est une partie bien définie de la norme C ++. Laisser les personnes qui aiment redéfinir les macros standard modifier le code dans votre projet rend votre code «vulnérable»; l'utilisationNULL
ne le fait pas.Eh bien, je préconise de ne pas utiliser du tout les pointeurs 0 ou NULL lorsque cela est possible.
Leur utilisation entraînera tôt ou tard des erreurs de segmentation dans votre code. D'après mon expérience, cela et les pointeurs en géréral sont l'une des plus grandes sources de bogues en C ++
aussi, cela conduit à des instructions "if-not-null" partout dans votre code. Beaucoup plus agréable si vous pouvez toujours compter sur un état valide.
Il existe presque toujours une meilleure alternative.
la source
0
) est utile pour le débogage. Bien mieux que de déréférencer des déchets aléatoires et d'obtenir qui sait quel résultat.Définir un pointeur sur 0 n'est tout simplement pas si clair. Surtout si vous venez dans un langage autre que C ++. Cela inclut C ainsi que Javascript.
J'ai récemment delt avec du code comme ceci:
virtual void DrawTo(BITMAP *buffer) =0;
pour une fonction virtuelle pure pour la première fois. J'ai pensé que c'était un jiberjash magique pendant une semaine. Quand j'ai réalisé qu'il s'agissait simplement de définir le pointeur de fonction sur a
null
(car les fonctions virtuelles ne sont que des pointeurs de fonction dans la plupart des cas pour C ++), je me suis lancé.virtual void DrawTo(BITMAP *buffer) =null;
aurait été moins déroutant que cette basterdation sans un espacement approprié pour mes nouveaux yeux. En fait, je me demande pourquoi C ++ n'emploie pas les minuscules
null
comme il emploie les minuscules faux et vrai maintenant.la source