calloc (), pointeurs et tous les bits zéro

Dupliquer possible:
NULL est-il toujours nul en C?

La norme C stipule ce qui suit pour calloc() :

La fonction calloc alloue de l’espace à un tableau d’objects nmemb dont la taille correspond à la taille. L’espace est initialisé à tous les bits zéro.

avec la mise en garde suivante relative à tous les bits zéro :

Notez que cela ne doit pas nécessairement être identique à la représentation du zéro à virgule flottante ou d’une constante de pointeur nulle.

Programme de test:

 #include  #include  #include  int main() { char** list = calloc(10, sizeof(*list)); int i; for (i = 0; i < 10; i++) { printf("%p is-null=%d\n", list[i], NULL == list[i]); } free(list); return 0; } 

J’ai construit et exécuté ce programme avec les compilateurs suivants:

  • VC7, VC8, VC9, VC10
  • gcc v4.1.2, gcc v4.3.4
  • Forte 5.8, Forte 5.10

Dans tous les cas, tous les bits zéro est un pointeur NULL (sauf si j’ai commis une erreur dans le programme de test).

Quelle est la raison pour laquelle un pointeur NULL n’est pas garanti par le standard C comme étant tous les bits zéro ? Par curiosité, y a-t-il des compilateurs où tous les bits zéro ne sont pas un pointeur NULL ?

La FAQ com.lang.c répond à cette question à la question 5.16 , où elle explique pourquoi cela se produit, et à la question 5.17 , où elle donne des exemples de machines réelles avec une NULL différente de zéro. Un cas relativement “courant” est que l’adresse 0 soit valide, donc une adresse invalide différente est sélectionnée pour NULL . Un exemple plus ésotérique est la machine Lisp Symbolics, qui n’a même pas de pointeur tel que nous les connaissons.

Il ne s’agit donc pas vraiment de choisir le bon compilateur. Sur un système moderne adressable sur des octets, avec ou sans mémoire virtuelle, il est peu probable que vous renconsortingez un pointeur NULL que l’adresse 0.

La norme C est soigneusement conçue pour prendre en charge un matériel totalement bizarre, et ce n’est que l’un des résultats. Un autre problème étrange dans le même sens est qu’il est possible de sizeof(void *) != sizeof(int *) , mais vous ne le verrez jamais arriver sur une architecture adressable sur des octets.

Oui, il existe certaines implémentations (certaines d’entre elles sont exotiques), où la représentation interne du pointeur NULL n’est pas égale à zéro. Cette section de la FAQ C est très intéressante (particulièrement celles-ci: 1 et 2 ).