Quelle est la différence entre un pointeur pointant vers l'emplacement 0x0 et un pointeur défini sur NULL?


12

Un pointeur pointant vers 0x0000 est-il identique à un pointeur défini sur NULL? Si la valeur NULL est définie dans le langage C, à quel emplacement se traduit-elle physiquement? Est-ce la même chose que 0x0000. Où puis-je trouver plus de détails sur ces concepts?


1
Cela a déjà été demandé sur Stack Overflow - stackoverflow.com/questions/1296843/… . Je pense que c'est limite pour nous, mais je suis prêt à lui donner le bénéfice du doute pour le moment.
ChrisF

Réponses:


12

Un point que la plupart des réponses ici ne traitent pas, du moins pas explicitement, est qu'un pointeur nul est une valeur qui existe pendant l'exécution, et une constante de pointeur nul est une construction syntaxique qui existe dans le code source C.

Une constante de pointeur nul , comme l'indique correctement la réponse de Karlson, est soit une expression de constante entière avec la valeur 0 (un simple 0est l'exemple le plus courant), soit une telle expression transtypée en void*(telle que (void*)0).

NULLest une macro, définie dans <stddef.h>et plusieurs autres en-têtes standard, qui se développe en une constante de pointeur nul définie par l'implémentation . L'expansion est généralement soit 0ou ((void*)0)(les parenthèses externes sont nécessaires pour satisfaire les autres règles de langage).

Ainsi, un littéral 0, lorsqu'il est utilisé dans un contexte qui nécessite une expression de type pointeur, est toujours évalué à une null pointer, c'est-à-dire une valeur de pointeur unique qui ne pointe vers aucun objet. Cela ne n'implique rien au sujet de la représentation d'un pointeur NULL . Les pointeurs nuls sont très souvent représentés sous forme de bits zéro, mais ils peuvent être représentés comme n'importe quoi. Mais même si un pointeur nul est représenté par , ou est toujours une constante de pointeur nul .0xDEADBEEF0(void*)0

Cette réponse à la question sur stackoverflow couvre bien cela.

Cela implique, entre autres, que memset()ou calloc(), qui peut définir une région de mémoire sur tous les bits à zéro, ne définira pas nécessairement les pointeurs de cette région sur des pointeurs nuls. Ils sont susceptibles de le faire sur la plupart des implémentations, mais le langage ne le garantit pas.

Je ne sais pas pourquoi cette question n'est pas considérée comme un double de celle-ci , ni comment elle est d'actualité ici.


1
L'un de mes problèmes avec la conception et l'évolution de C est que le chiffre zéro a continué d'être utilisé comme représentation non obsolète d'un pointeur nul. À l'époque des premiers jours du langage (par exemple avant l'avènement de choses comme les prototypes de fonctions), les pointeurs et les entiers étaient suffisamment interchangeables pour que l'utilisation de "0" pour un pointeur nul soit simple et "fonctionne tout simplement". Cependant, une fois qu'il est devenu nécessaire de faire la distinction entre la quantité entière zéro et un pointeur nul, la représentation "0" aurait dû être déconseillée au profit d'un mot clé ou d'une séquence d'opérateurs.
supercat

Cela signifie-t-il que le pointeur NULL peut en fait pointer vers un emplacement lorsqu'il est affecté NULL en fonction de la plateforme? La constante du pointeur nul peut être une construction syntaxique, mais que se passe-t-il exactement lorsque le code s'exécute? Supposons que cette construction syntaxique ait été compilée sur la plate-forme GNU / Linux. Quelle est la valeur du pointeur lorsque nous lui attribuons NULL? En quoi cette adresse diffère-t-elle de toute autre adresse?
Arpith

1
@Arpith: L'affectation NULL, ou toute constante de pointeur nul , à un objet pointeur définit la valeur de cet objet sur un pointeur nul . Au niveau de la machine, cela peut bien indiquer un morceau de mémoire valide. Déréférencer un pointeur nul a un comportement indéfini; accéder à un morceau de mémoire à l'adresse 0x0000000est un comportement valide, comme c'est littéralement toute autre chose. Cette adresse diffère de toute autre adresse par (a) une comparaison égale à NULL, et (b) une comparaison inégale à tout pointeur vers un objet C. Un pointeur nul est une valeur de pointeur arbitraire utilisée pour indiquer qu'il ne pointe vers rien.
Keith Thompson

1
Au niveau de la machine, il peut pointer vers une partie de mémoire valide, mais dans la plupart des environnements C, il pointera vers une mémoire non valide, de sorte que toute tentative d'utilisation du pointeur entraînera une interruption / panne / exception matérielle. Ce n'est généralement que sur les plates-formes matérielles les plus simples --- celles qui ne prennent pas en charge la gestion de la mémoire --- où un pointeur NULL pointe vers un emplacement mémoire valide.
Solomon Slow

7

Chaque plate-forme est libre de définir NULL à sa guise.

Selon la norme C, si vous affectez zéro à un pointeur, il sera converti en valeur NULL (pour cette plate-forme). Cependant, si vous prenez un pointeur NULL et le transformez en entier, rien ne garantit que vous obtiendrez zéro sur chaque plate-forme là-bas. Le fait est cependant que sur la plupart des plateformes, il sera nul.

Informations sur ce genre de choses que vous pouvez trouver dans le langage C Spécification . Une source, dont je ne peux pas garantir la fiabilité, est la suivante: http://www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
S'ils choisissent de rompre avec la norme, ils sont libres de redéfinir NULL pointer constant. Pour autant que je sache, il n'y a pas de compilateurs qui font cela.
Karlson

Existe-t-il un compilateur qui n'implémente pas NULL comme 0? Et NULL est-il garanti comme faux?
ugoren

NULL est garanti comme faux à la norme. Je ne sais pas s'il existe un compilateur (plate-forme, en fait) qui n'implémente pas NULL comme 0, et j'en doute sérieusement, mais la norme ne l'interdit pas, alors qui sait.
Mike Nakis

Il y a confusion entre la représentation de la « constante de pointeur NULL » abstrait (comme mentionné dans la spécification) en mémoire, ce qui peut être aussi le qui plaît fabricant de plate - forme et la définition de NULLmacro, qui doit étendre à 0en C ++ et soit 0ou (void *)0en C, parce que c'est la vraie "constante de pointeur nul".
Jan Hudec

Bien que NULL puisse en théorie être défini comme n'importe quoi, il existe cependant une garantie par la norme qu'une constante int avec la valeur 0 transtypée en un pointeur se traduira par un pointeur nul (ISO 9899: 1999 6.3.2.3/3). La macro NULL de stddef.h doit être un pointeur nul (7.17 / 3), il serait donc très lourd pour le compilateur de ne pas implémenter NULL en tant que 0 ou (void *) 0.

1

Il est défini dans le langage C car il n'y a aucune adresse de machine invariante à laquelle il correspond. Si c'était le cas, nous n'aurions pas besoin d'une abstraction! Même si sur la plupart des plates-formes, NULL peut éventuellement être implémenté en tant que 0 d'un type ou d'un autre, il est tout simplement faux de supposer qu'il en est ainsi universellement, si vous vous souciez de la portabilité.


C'est ce que sont les normes pour open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
Karlson

0

Selon la section du document standard C6.3.2.3 :

Une expression de constante entière avec la valeur 0, ou une telle expression transtypée en type void *, est appelée constante de pointeur nul.55) Si une constante de pointeur nulle est convertie en type de pointeur, le pointeur résultant, appelé pointeur nul, est garantie de comparer inégale à un pointeur sur n'importe quel objet ou fonction.

Jusqu'à présent, je n'ai pas vu de compilateur qui en soit sorti.


@ PéterTörök Vous avez raison, c'est une erreur. :)
Karlson

1
Oui, mais notez qu'il ne dit rien sur le pointeur ayant réellement une valeur numérique de 0. Ce n'est peut-être pas le cas, bien que sur la plupart des plates-formes cela soit le cas.
Jan Hudec
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.