69 votes

Comment écrire du code C/C++ correctement lorsque le pointeur null n’est pas tous les bits à zéro

En tant que c-faq dit (http://c-faq.com/null/machexamp.html) il y a des architectures où pointeur null est pas tous les bits à zéro. La question est donc de ce fait les vérifications de la construction suivante:

void* p = get_some_pointer();
if (!p) 
    return;

Suis-je en comparant p avec dépend de la machine de pointeur null ou je suis en comparant p arithmétiques de zéro?

Dois-je écrire

void* p = get_some_pointer();
if (NULL == p) 
    return;

au lieu d'être prêt pour de telles architectures ou c'est juste de la paranoïa?

100voto

ivaigult Points 401

Selon le C spéc.:

Une constante entière expression avec la valeur 0, ou une expression fonte de type void *, est appelé un pointeur null constante. 55) Si une valeur null pointeur constant est converti en un type pointeur, la pointeur, appelé un pointeur null, c'est la garantie de comparer l'inégalité à une pointeur vers un objet ou une fonction.

Donc, 0 est un pointeur null constante. Et si nous le convertir en un type pointeur, nous allons obtenir un pointeur null qui peut être non-tous les bits à zéro pour certaines architectures. Ensuite nous allons voir ce que la spec dit à propos de la comparaison de pointeurs et d'un pointeur null constante:

Si l'un des opérandes est un pointeur et l'autre est un pointeur null constante, le pointeur null constant est convertie dans le type de l'indicateur.

Considérons (p == 0): premier 0 , est converti en un pointeur null, et puis, p est comparé avec un pointeur null constante dont la valeur des bits sont dépendants de l'architecture.

Ensuite, voir ce que la spec dit à propos de l'opérateur de négation:

Le résultat de la négation logique de l'opérateur ! est 0 si la valeur de ses opérande compare inégale à 0, 1 si la valeur de son opérande compare égal à 0. Le résultat est de type int. L'expression !E est équivalent (0==E).

Cela signifie qu' (!p) est équivalent à (p == 0) qui est, selon la spécification, test p contre la machine défini pointeur null constante.

Ainsi, vous pouvez écrire en toute sécurité if (!p) même sur les architectures où le pointeur null constante n'est pas tous les bits à zéro.

Comme pour le C++, un pointeur null constante est définie comme:

Un pointeur null constante est une partie intégrante expression constante (5.19) prvalue de type entier qui prend la valeur zéro ou un prvalue de type std::nullptr_t. Un pointeur null constante peut être converti en un pointeur type; le résultat est la valeur de pointeur null de ce type et est à distinguer de tous les autres de la valeur de pointeur d'objet ou de la fonction type de pointeur.

Ce qui est proche de ce que nous avons pour le C, plus l' nullptr de la syntaxe de sucre. Le comportement de l'opérateur == est défini par:

En outre, les pointeurs, les membres peuvent être comparés, ou un pointeur vers membre et d'un pointeur null constante. Pointeur sur membre des conversions (4.11) et de la qualification des conversions (4.4) sont effectuées afin de leur apporter pour un type commun. Si l'un des opérandes est un pointeur null constante, l' type le plus commun est le type de l'autre opérande. Sinon, la commune le type est un pointeur de type de membre similaires (4.4) le type de l'un des les opérandes, avec un cv-qualification signature (4.4) qui est le de l'union de la cv-qualification des signatures de l'opérande types. [ Note: ceci implique que toute pointeur de membre ne peut être comparé à une valeur null pointeur constant. - la note de fin ]

Qui mène à la conversion de 0 pour un type de pointeur (comme en C). Pour l'opérateur de négation:

Le résultat de la négation logique de l'opérateur ! est 0 si la valeur de ses opérande compare inégale à 0, 1 si la valeur de son opérande compare égal à 0. Le résultat est de type int. L'expression !E est équivalent (0==E).

Donc, if (!p) est sans danger pour C++.

Un autre cas pourrait être if (p), mais c'est OK aussi, depuis le C++ spec dit qu'une valeur de pointeur null seront convertis en bool comme false:

Une valeur de zéro, la valeur de pointeur null, ou null membre de la valeur du pointeur est converti à faux;

32voto

Yu Hao Points 40603

Il n'a pas d'importance si NULL est tout à zéro ou pas dans la machine réelle. En supposant p est un pointeur:

if (!p) 

est toujours un moyen légal pour tester si p est un pointeur null, et c'est toujours équivalent à:

if (p == NULL)

Vous pouvez être intéressé par un autre C-FAQ de l'article: C'est étrange. La valeur NULL est garanti à 0, mais le pointeur null est pas?


Ci-dessus est vrai pour C et C++. Notez qu'en C++(11), il est préférable d'utiliser nullptr de pointeur null littérale.

10voto

Lundin Points 21616

Cette réponse s'applique à C.

Ne mélangez pas les valeurs NULL avec les pointeurs null. La valeur NULL est juste une macro garanti d'être un pointeur null constante. Un pointeur null constante est garantie soit 0 ou (void*)0.

De C11 6.3.2.3:

Une constante entière expression avec la valeur 0, ou une expression fonte de type void *, est appelé un pointeur null constante 66). Si une valeur null pointeur constant est converti en un type pointeur, la pointeur, appelé un pointeur null, c'est la garantie de comparer l'inégalité à une pointeur vers un objet ou une fonction.

66) La macro NULL est définie dans (et d'autres en-têtes) comme un pointeur null constante; voir 7.19.

7.19:

Les macros sont

NULL

qui se développe pour une mise en œuvre définies par pointeur null constante;

La mise en œuvre définies dans le cas de NULL, 0 ou void*. NULL ne peut pas être autre chose.

Toutefois, lorsqu'un pointeur null constante est converti en un pointeur, vous obtenez un pointeur null, ce qui n'est pas nécessairement égale à la valeur zéro. Le code if (!p) n'a rien à voir avec le NUL de la macro, vous comparez un pointeur nul contre l'arithmétique de la valeur zéro.

Donc, en théorie, le code comme celui - int* p = NULL peut entraîner un pointeur null p qui est différente de zéro.

7voto

Glenn Teitelbaum Points 3564

Retour dans la journée, les ordinateurs STRATUS eu pointeurs null en tant que 1 dans toutes les langues.

Cela a causé des problèmes pour C, donc leur compilateur C permettrait la comparaison pointeur de 0 et 1 pour retourner true

Cela permettrait :

À sur un ptr null même si vous avez pu voir que avait une valeur de 1 dans le débogueur

Serait en fait d’imprimer « Bienvenue à STRATUS »

1voto

Joshua Points 13231

Si votre compilateur est tout bon il y a deux choses (et seulement deux choses) à surveiller.

1 : statique par défaut initialisée (c’est, non assigné) pointeurs n’aurez NULL en eux.

2 : memset() sur une struct ou un tableau, ou par extension calloc() ne valeur pointeurs NULL.

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