Comment vérifier si un pointeur est un pointeur NULL?

Je pense toujours simplement if(p != NULL){..} fera l’affaire. Mais après avoir lu cette question Stack Overflow , il semble que non.

Alors, quel est le moyen canonique de rechercher des pointeurs NULL après avoir absorbé toutes les discussions de cette question qui dit que les pointeurs NULL peuvent avoir une valeur non nulle?

    Je pense toujours simplement si (p! = NULL) {..} fera l’affaire.

    Ce sera.

    Tout d’abord, pour être clair à 100%, il n’y a pas de différence entre C et C ++ ici. Et deuxièmement, la question de débordement de stack que vous citez ne parle pas de pointeurs nuls; il introduit des pointeurs non valides; des pointeurs qui, du moins en ce qui concerne la norme, provoquent un comportement indéfini simplement en essayant 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 existe trois méthodes répandues pour rechercher un pointeur nul:

     if ( p != NULL ) ... if ( p != 0 ) ... if ( p ) ... 

    Tout fonctionne, indépendamment de la représentation d’un pointeur null sur la machine. Et tous, d’une manière ou d’une autre, sont trompeurs; lequel vous choisissez est une question de choisir le moins mauvais. Formellement, les deux premiers sont identiques pour le compilateur; la constante NULL ou 0 est convertie en un pointeur nul du type de p , et les résultats de la conversion sont comparés à p . Indépendamment de la représentation d’un pointeur nul.

    La troisième est légèrement différente: p est implicitement converti en bool . Mais la conversion implicite est définie comme les résultats de p != 0 , vous vous retrouvez donc avec la même chose. (Ce qui signifie qu’il n’y a vraiment aucun argument valable pour utiliser le troisième style: il obscurcit avec une conversion implicite, sans aucun avantage compensatoire.)

    Lequel des deux premiers choix est en grande partie une question de style, peut-être partiellement dicté par votre style de programmation ailleurs: selon le langage utilisé, l’un des mensonges sera plus gênant que l’autre. Si c’était seulement une question de comparaison, je pense que la plupart des gens préféreraient NULL , mais dans quelque chose comme f( NULL ) , la surcharge qui sera choisie est f( int ) et non une surcharge avec un pointeur. De même, si f est un modèle de fonction, f( NULL ) instanciera le modèle sur int . (Bien entendu, certains compilateurs, tels que g ++, généreront un avertissement si NULL est utilisé dans un contexte sans pointeur; si vous utilisez g ++, vous devez utiliser NULL .)

    En C ++ 11 , bien sûr, l’idiome préféré est:

     if ( p != nullptr ) ... 

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

    Le compilateur doit fournir un système de types cohérent et un ensemble de conversions standard. Ni la valeur entière 0 ni le pointeur NULL ne doivent être représentés par des bits nuls, mais le compilateur doit prendre soin de convertir le jeton “0” dans le fichier d’entrée en une représentation correcte pour l’entier zéro et la conversion en type de pointeur. doit convertir un entier en représentation de pointeur.

    L’implication de ceci est que

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

    il n’est pas garanti que tous les systèmes cibles se comportent de la même manière, car vous faites ici une hypothèse sur le modèle de bits.

    Par exemple, ma plate-forme intégrée ne dispose pas de protection de mémoire et conserve les vecteurs d’interruption à l’adresse 0; ainsi, par convention, les entiers et les pointeurs sont XORés avec 0x2000000 lorsqu’ils sont convertis, ce qui laisse (void *) 0 pointant sur une adresse génère une erreur de bus lors de la déréférence, cependant le test du pointeur avec une instruction if renvoie d’abord une représentation sous forme de nombre entier, qui est ensuite un zéro absolu.

    La représentation réelle d’un pointeur nul est sans importance ici. Un littéral entier de valeur zéro (y compris 0 et toute définition valide de NULL ) peut être converti en tout type de pointeur, ce qui donne 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 nulles du pointeur null si vous écrivez quelque chose de tordu tel que p != reinterpret_cast(0) , ne le faites pas.

    Bien que je viens de remarquer que votre question porte les balises C et C ++. Ma réponse fait référence à C ++, et d’autres langages peuvent être différents. Quelle langue utilisez-vous?

    Apparemment, le sujet que vous mentionnez concerne le C++ .

    En C votre extrait fonctionnera toujours. J’aime le plus simple if (p) { /* ... */ } .

    La représentation des pointeurs n’a pas d’importance pour les comparer, car toutes les comparaisons en C ont lieu comme des valeurs et non des représentations. La seule façon de comparer la représentation serait quelque chose de hideux comme:

     static const char ptr_rep[sizeof ptr] = { 0 }; if (!memcmp(&ptr, ptr_rep, sizeof ptr)) ... 

    Eh bien, cette question a été posée et répondue en 2011, mais il existe nullptr en C ++ 11 . C’est tout ce que j’utilise actuellement.

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