Comment vérifier si un pointeur est NULL pointer?

je pense toujours que tout simplement if(p != NULL){..} fera l'affaire. Mais après avoir lu cette question de débordement de pile , il semble que non.

alors quelle est la façon canonique de vérifier les pointeurs NULS après absorbant toute la discussion dans cette question qui dit que les pointeurs NULS peuvent avoir une valeur non nulle?

35
demandé sur ivan_pozdeev 2011-05-31 13:52:40

7 réponses

j'ai toujours pense simplement if(p != NULL.{).} va faire le travail.

il le fera.

43
répondu cnicutar 2018-07-05 09:45:01

D'abord, pour être 100% clair, il y a Non différence entre C et c++ ici. Et deuxièmement, la question de débordement de pile que vous citez ne parle pas de pointeurs null; elle introduit des pointeurs invalides; pointeurs qui, au moins autant que le standard est concerné, provoquer un comportement non défini juste en essayant de les comparer. Il n'y a aucun moyen de vérifier en général si un pointeur est valide.

à la fin, il ya trois façons répandues de vérifier pour un pointeur nul:

if ( p != NULL ) ...

if ( p != 0 ) ...

if ( p ) ...

tout le travail, indépendamment de la représentation d'un pointeur nul sur le 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 indentiques pour le compilateur; la constante NULL ou 0 est convertie à un pointeur nul du type p , et les résultats de la conversion sont comparés à p . Quel que soit le la représentation d'une valeur null pointeur.

le troisième est légèrement différent: p est implicitement converti à bool . Mais la conversion implicite est définie comme les résultats de p != 0 , donc vous finissez avec la même chose. (Ce qui signifie qu'il n'y a vraiment aucun argument valide pour utiliser le troisième style-il obscurcit avec une conversion implicite, sans contrepartie.)

lequel des deux premiers que vous préférez est en grande partie une question de style, peut-être partiellement dicté par votre style de programmation ailleurs: selon l'idiome, l'une des mensonges seront plus gênant que les autres. Si ce n'était qu'une question de comparaison, je pense que la plupart les gens seraient favorables à NULL , mais dans quelque chose comme f( NULL ) , le la surcharge qui sera choisie est f( int ) , et non une surcharge avec une pointeur. De même, si f est un modèle de fonction, f( NULL ) sera instanciez le modèle sur int . (Bien sûr, certains compilateurs, comme g++, générera un avertissement si NULL est utilisé dans un contexte sans pointeur; si vous utilisez g++, vous devriez vraiment utiliser NULL .)

Dans C++11 , bien sûr, le préféré de l'idiome est:

if ( p != nullptr ) ...

, qui évite la plupart des problèmes avec les autres solutions. (Mais il n'est pas C-compatible:-).)

24
répondu James Kanze 2016-01-27 12:55:59

le compilateur doit fournir un système de type cohérent et un ensemble de conversions standard. Ni la valeur entière 0 ni le pointeur nul N'ont besoin d'être représentés par des bits tout-zéro, mais le compilateur doit prendre soin de convertir le jeton "0" dans le fichier d'entrée à la représentation correcte pour le zéro entier, et le cast au type de pointeur doit convertir de la représentation entière à la représentation de pointeur.

l'implication de ceci est que

void *p;
memset(&p, 0, sizeof p);
if(p) { ... }

n'est pas garanti de se comporter de la même façon sur tous les systèmes cibles, car vous faites une supposition sur le modèle de bits ici.

par exemple, j'ai une plate-forme intégrée qui n'a pas de protection mémoire, et qui garde les vecteurs d'interruption à l'adresse 0, donc par convention, les entiers et les pointeurs sont Xorés avec 0x2000000 lorsque convertis, ce qui laisse (nul *)0 pointant vers une adresse qui génère une erreur de bus lorsque déréférencés, cependant testant le pointeur avec un La déclaration if la retournera d'abord à la représentation entière, qui est alors tout-zéros.

9
répondu Simon Richter 2011-05-31 10:44:28

la représentation réelle d'un pointeur nul n'est pas pertinente ici. Un entier littéral avec une valeur zéro (y compris 0 et toute définition valide de NULL ) peut être converti en n'importe quel type de pointeur, donnant un pointeur nul, quelle que soit la représentation réelle. Donc p != NULL , p != 0 et p sont tous des tests valides pour un pointeur non nul.

vous pourriez rencontrer des problèmes avec les représentations non-zéro du pointeur nul si vous avez écrit quelque chose de tordu comme p != reinterpret_cast<void*>(0) , donc ne fais pas ça.

bien que je viens de remarquer que votre question est marquée C aussi bien que C++. Ma réponse fait référence C++, et d'autres langues peuvent être différentes. Quelle langue utilisez-vous?

6
répondu Mike Seymour 2011-05-31 10:38:49

apparemment, le fil dont vous parlez est d'environ C++ .

Dans C votre extrait de le sera toujours. J'aime le plus simple if (p) { /* ... */ } .

4
répondu pmg 2011-05-31 09:55:09

la représentation des pointeurs n'est pas pertinente pour les comparer, puisque toutes les comparaisons en C ont lieu sous la forme de valeurs pas de représentations. La seule façon de comparer la représentation serait quelque chose d'hideux comme:

static const char ptr_rep[sizeof ptr] = { 0 };
if (!memcmp(&ptr, ptr_rep, sizeof ptr)) ...
2
répondu R.. 2011-05-31 12:58:40

Eh bien, cette question a été posée et a reçu une réponse en 2011, mais il y a nullptr dans C++11 . C'est tout ce que j'utilise actuellement.

vous pouvez lire plus de Stack Overflow et aussi de cet article .

1
répondu JohnJohn 2017-05-23 12:25:48