Comment vérifier si un pointeur de pointeur NULL?
Je pense toujours simplement if(p != NULL){..}
va faire le travail. Mais après la lecture de ce Débordement de Pile question, il ne semble pas.
Alors, quelle est la manière canonique pour vérifier des pointeurs NULL après l'absorption de la discussion à cette question qui dit pointeurs NULL peut avoir une valeur non nulle?
- Ce n'est pas c...c'est un c++ fil... personnellement, j'irais avec:
if(p) {...}
- Vous vous faites trop de - votre code est très bien, même en C++. Que le débat était entre certains de langue avocats - c'est une sorte de "combien d'anges peuvent danser sur la tête de la broche" choses".
- va
if(p)
être différent deif(p != NULL)
? - lorsque vous n'avez pas inclus un fichier d'en-tête qui définit la valeur NULL, on va compiler, de l'autre l'habitude...
- ce cas ,c'est différent 🙂 Mais vous n'avez pas mentionné ce qui est discuté dans ce thread,qui dit parfois des pointeurs NULL peut avoir une valeur non nulle...Dans ce cas,les deux
if(p)
etif(p!=NULL)
échoue,je pense. - L'interne rep d'un pointeur NULL peut, en théorie, avoir une valeur non nulle (en fait, ils ne le font pas), mais ce n'est rien pour vous de vous inquiéter.
- Butterworth ,si le représentant de pointeur NULL n'est pas un non-zéro,les deux
if(p)
etif(p!=NULL)
échoue,je n'ai pas de raison de ne pas s'inquiéter à ce sujet. - Non, ils ne seront pas parce qu'ils ne sont pas à l'aide de l'interne rep - votre code est bien! C'est la façon dont TOUS les code C et TOUS les code C++ est écrit: ce thread est un résumé des débats intellectuels sur le libellé de la norme C++. Vous obtenez beaucoup de ce sur le C++ balises.
- Butterworth ,deux fils sur le même sujet par les deux réponse différente,mais je décide de coller à la mienne:)
- en C, même
if (p != 0)
va "travailler" lors de la représentation interne n'est pas tous les bits à zéro. - Ack! Je pense que le point est que, même si en interne NULL n'est pas 0, un pointeur null aura toujours la valeur NULL. Il suffit de ne pas
#define NULL p
, et de garder le sourire. - et en C++ aussi. Ma tentative de l'expliquer: dans les deux langues,
NULL
est un pointeur null, sinon il convertit un pointeur null (en C, il est dépendant de l'implémentation qui, en C++, c'est toujours le dernier). Et dans les deux langues pointeurs null comparer l'égalité. C'est complètement hors de propos que de pointeurs null avoir tous les bits à zéro ou pas,0
(ou toute autre expression constante entière avec la valeur 0) etNULL
convertir aux pointeurs null, pas (forcément) des pointeurs avec tous les bits à zéro. - Ce thread explique si la valeur NULL peut être définie avec une valeur non nulle ou pas. C est à partir de C++, parce que en C++, NULL, 0, fin de l'histoire. En C, la valeur NULL est quelque chose de magique qui s'affiche lorsque vous transtypage de l'entier 0 en un pointeur.
- À la fois le C et le C++ sont (presque) identiques à cet égard. Vous ne pouvez pas comparer directement un pointeur avec un
int
. Leint
doit d'abord être converti en un pointeur. Si (et seulement si) leint
est partie intégrante de l'expression constante de l'évaluation à 0, il y a une conversion implicite, ce qui résulte en un pointeur null. (Dans C, il existe une autre possibilité). Les résultats de cette conversion va être tout ce que la mise en œuvre exige. Et si vous écrivez simplementif (p)
, le langage définit ce sera l'équivalent exact deif (p != 0)
. - Les exigences pour la définition de
NULL
sont identiques, mot pour mot, dans le C et le C++ standard. Dans les deux cas, il se définir comme un "pointeur null constante". Traditionnellement,0
, mais tout "de la constante expression intégrale de l'évaluation à 0" est autorisée; en C, la définition de "pointeur null constante" permet aussi de cette à être jeté àvoid*
, mais qui n'a vraiment pas de changer quoi que ce soit. Dans les deux cas, la conversion d'un pointeur null constante dans un pointeur null est le compilateur de la magie. - Pour garder les questions plus clair:
NULL
est une macro définie dans<stddef.h>
(et quelques autres en-têtes).NULL
n'est pas un pointeur null; il faut être défini comme un "pointeur null constante" (qui est en C++, ne peut pas être un pointeur, et en C, traditionnellement, n'est pas un pointeur). Il y a trois concepts distincts qui doivent être traitées:NULL
, un pointeur null, et d'un pointeur null constante. Et comment un pointeur null est physiquement représenté (sa séquence de bits) est complètement indépendante des deux autres. - J'ai enlevé c++ parce qu'en C++, la situation est complètement différente: stackoverflow.com/questions/17772103/...
Vous devez vous connecter pour publier un commentaire.
Il sera.
NULL
est défini à quelque chose de non-braindead.p
est équivalent àp != NULL
, et c'est purement une question d'esthétique qui vous choisissez. Ni est plus sûr ou de la "meilleure pratique" que les autres.if (p)
signifie en faitif (p != NULL)
, pourquoi cacher ce fait au lecteur.if (p)
légèrement plus clair que ça n'introduisent pas de bruit inutile; les autres à trouver votre préférence légèrement plus clair que c'est plus explicite; et personne n'ayant aucune expérience trouverez l'une des formes floues. Il n'y a certainement aucune raison de le décrire comme "généralement mieux" ou "plus sûrs et de meilleure pratique", sauf si votre entreprise est de vendre des normes de codage.if(*(ptr+1))
et de le comparer àif(*(ptr+1) == NULL)
. Seul ce dernier cas, il est évident que le type de ptr est un pointeur de pointeur et que nous nous sommes intéressés à son adresse.if (p)
parce que j'ai encore à s'arrêter et à réfléchir à ce sujet. Comme vous le dites, c'est probablement une question d'expérience; j'ai seulement été à l'aide de C et de C++ depuis 30 ans, donc pas de doute qu'il va venir à moi dans le temps. (Sérieusement, il peut être question d'une autre expérience, j'ai utilisé Pascal et Modula-2 largement avant de commencer avec le C, et avait déjà habitué à typage strict. Je n'ai jamais senti à l'aise avec le C du jeu ici, avec les conversions implicites de tous sur la place.)NULL
), même sip
n'est pas un pointeur vers un pointeur, auquel cas le supplément de bruit est alors trompeuse et inutile. Mais, comme je le dis toujours, c'est vraiment pas la peine de polémiquer sur mineur esthétique des points, sauf si (comme MISRA) vous êtes dans l'entreprise de vente de normes de codage.if (p)
idiome est assez largement utilisé et je suis certain qu'au moins certains programmeurs lire sans problèmes. Tous les endroits où j'ai travaillé ont insisté surif (p != NULL)
dans leurs directives de codage, de sorte que même en C ou C++, je ne suis pas habitué à voir ça.(void*)0
n'est pas une définition valable pourNULL
; il doit être convertibles à tout type pointeur, et le C++ ne permet pas les conversions implicites devoid*
à d'autres types de pointeur. DoncNULL
doit être défini comme une valeur zéro littéral de type entier, et en comparant à un autre type numérique ne vais pas donner un avertissement. (C++0x régler cette question en introduisantnullptr
, d'un type qui convertibles de type pointeur, mais pas les types numériques, mais jusqu'alors, nous avons juste à se débrouiller du mieux que nous le pouvons).Tout d'abord, pour être 100% clair, il est pas différence entre le C et le C++
ici. Et la deuxième, le Dépassement de Pile question que vous citez ne parle pas de pointeurs null; elle présente des pointeurs invalides; les pointeurs qui, au moins autant que le
la norme est concerné, provoquer un comportement non défini en essayant simplement de
les comparer. Il n'y a aucun moyen de tester, en général, si un pointeur est
valide.
En fin de compte, il y a trois généralisée des moyens de vérifier pour un pointeur null:
Tous les travaux, quelle que soit la représentation d'un pointeur null sur la
de la machine. Et tous, d'une manière ou d'une autre, sont trompeurs; celui qui vous
choisir est une question de choisir le moins mauvais. Officiellement, les deux premiers
sont identique pour le compilateur; la constante
NULL
ou0
est convertid'un pointeur null dans le type de
p
, et les résultats de la conversionsont comparés à
p
. Quelle que soit la représentation d'une valeur nullpointeur.
Le troisième est un peu différent:
p
est implicitement convertipour
bool
. Mais la conversion implicite est défini comme le résultat dep
, pour se retrouver avec la même chose. (Ce qui signifie qu'il n'y a!= 0
vraiment pas un argument valide pour l'utilisation de la troisième style ce trouble
avec une conversion implicite, sans contrepartie.)
Dont l'un des deux premiers que vous préférez est en grande partie une question de style, de
peut-être en partie dicté par votre style de programmation ailleurs:
selon l'idiome, l'une des mensonges seront plus gênant
que les autres. Si c'était seulement une question de comparaison, je pense que la plupart des
les gens seraient favorables à
NULL
, mais dans quelque chose commef( NULL )
, l'la surcharge qui sera choisie est
f( int )
, et non pas d'une surcharge avec unpointeur. De même, si
f
est un modèle de fonction,f( NULL )
vainstancier le modèle de
int
. (Bien sûr, certains compilateurs, commeg++, va générer un message d'avertissement si
NULL
est utilisé dans un non-pointeur de contexte;si vous utiliser g++, vous devriez vraiment utiliser
NULL
.)Dans C++11, bien sûr, le préféré de l'idiome est:
ce qui évite la plupart des problèmes avec les autres solutions. (Mais il
n'est pas C-compatible:-).)
void *p = main;if(p == 0x4004e3)printf("1\n");
imprime1
(ici0x4004e3
doit être remplacé par l'adresse réelle demain
). Cela dit,un pointeur peut être utilisé pour comparer avec un entier,et aucune conversion n'est impliqué.main
a, en effet, d'une nature très particulière; je ne pense pas qu'il existe un moyen d'obtenir son adresse, au moins en C++, et si vous le pouvez, il n'y a rien que vous pourriez faire avec elle. Mais en général, il n'y a pas de conversion implicite d'un pointeur de type à l'autre, sauf pour le cas particulier que toute pointeur de données peuvent être convertis à unvoid*
avec un cv de qualification. Si le code que vous citez compilé, le compilateur est cassé.int main(int argc,char *argv[]){...}
.main
, a fourni une déclaration demain
est visible; en C++, je ne suis pas sûr. Ni la langue, cependant, est-il une conversion implicite d'un pointeur de fonction àvoid*
, et vous ne pouvez pas comparer un pointeur et un entier, autre qu'un pointeur null constante. La première est souvent acceptée (avec ou sans avertissement), pour des raisons historiques; un compilateur qui accepte la seconde, cependant, est brisé.int* p_1=(int*)569;
(affectation de non de pointeur null-constantes),est-il légal ?reinterpret_cast
, qui que dit la norme est définie par l'implémentation," mais "est destiné à être rien de surprenant pour ceux qui connaissent l'adressage de la structure du sous-jacent de la machine."0x567
la représentation interne,if(p)
sera le même queif(p != 0x567)
,mais le plus tard est,comme vous l'avez dit,la mise en œuvre défini,droit? Et je peux même dire que dans ce cas, aucun objet ne se trouvent à l'adresse0x567
,est ce que le droit?Le compilateur doit fournir un système de type, et de fournir un ensemble de processus de conversion standard. Ni la valeur de l'entier 0, ni le pointeur NUL besoin d'être représenté par tous les zéro bits, mais le compilateur doit prendre soin de la conversion de l' "0" jeton dans le fichier d'entrée pour la représentation correcte pour l'entier zéro, et la fonte de type pointeur doit convertir entier de pointeur de la représentation.
La conséquence de cela est que
n'est pas garantie à se comporter de la même manière sur tous les systèmes cibles, que vous faites une hypothèse sur le modèle de bits ici.
Comme un exemple, j'ai une plate-forme intégrée qui n'a pas de protection de la mémoire, et garde les vecteurs d'interruption à l'adresse 0, donc, par convention, les entiers et les pointeurs sont XORed avec 0x2000000 lors de la conversion, ce qui laisse (void *)0 pointant vers une adresse qui génère une erreur de bus quand déréférencé, cependant tester le pointeur avec un
if
déclaration de retourner à la représentation entière la première, qui est ensuite tous les zéros.0
,void *0
,NULL
) comme un cas particulier,ce sujet lors de la comparaison d'un pointeur avec un entier différent de zéro?Merci de voir mon jour la question ci-dessus:)0
à unint
, puis explicitement la conversion queint
à un pointeur est autorisé à donner des résultats différents que la conversion implicite de la constante de0
à un pointeur.La représentation réelle d'un pointeur null est pas pertinente ici. Un littéral entier avec une valeur de zéro (y compris
0
et toute définition valable deNULL
) peut être converti en un pointeur de type, de donner un pointeur null, quelle que soit la représentation réelle. Doncp != NULL
,p != 0
etp
sont tous les tests valides pour un pointeur non null.Vous pourriez avoir des problèmes liés à la non-zéro représentations de pointeur null si vous avez écrit quelque chose de tordu comme
p != reinterpret_cast<void*>(0)
, afin de ne pas le faire.Bien que j'ai juste remarqué que votre question est étiqueté C et C++. Ma réponse fait référence C++, et d'autres langues peuvent être différentes. Quelle langue utilisez-vous?
Apparemment le fil que vous consultez est d'environ
C++
.Dans
C
votre extrait de le sera toujours. J'aime le plus simpleif (p) { /* ... */}
.if (p)
(if (p != NULL)
,if (p != 0)
) ouif (!p)
(if (p == NULL)
,if (p == 0)
); si c'est en C++, l'utilisation du C++ langage (je n'ai aucune idée de ce que c'est).La représentation des pointeurs est pas pertinent de les comparer, car toutes les comparaisons dans C lieu comme valeurs pas les représentations. La seule façon de comparer la représentation serait quelque chose de hideux comme:
!memcmp(ptr, ptr_rep, sizeof ptr)
au moins...ptr
, pas la représentation de ce qu'il désigne, de sorte que vous besoin de l'adresse de la variableptr
.void *dummy = sizeof(short)-2;
fait au moment de la compilation affirmation quesizeof(short)==2
(c'est seulement valide C si l'expression est évaluée à 0).0x567
la représentation interne,if(p)
sera le même queif(p != 0x567)
,mais le plus tard est,comme vous l'avez dit,la mise en œuvre défini,droit? Et je peux même dire que dans ce cas, aucun objet ne se trouvent à l'adresse0x567
,est ce que le droit?if (p != 0x567)
n'est pas valide C et ne compilera pas. Ce que vous entendez estif (p != (void *)0x567)
, mais cela a mise en œuvre-comportement défini et n'est pas nécessairement la même que la comparaison de la représentation.Bien, cette question a été posée et répondue le chemin du retour en 2011, mais il est
nullptr
dans C++11. C'est tout ce que j'utilise actuellement.Vous pouvez lire plus de Débordement de Pile et aussi de cet article.
if(p == nullptr) {}
. dans la réponse ainsi, il serait tout simplement une insulte à l'OP.nullptr
EST la manière canonique énoncées par l'officiel de la norme C++. Votre manque de décence de ne plus perdre mon temps.