72 votes

Pourquoi les pointeurs NULL sont-ils définis différemment en C et C ++?

En C, NULL est défini comme (void *)0 alors qu'en C ++, il est 0 . Pourquoi est-ce? Dans CI, on peut comprendre que si NULL n'est pas transtypé en typage à (void *) compilateurs peuvent / ne peuvent pas générer d'avertissement. Autre que cela, y a-t-il une raison?

102voto

templatetypedef Points 129554

En C++, le pointeur null est défini par la spécification ISO (§4.10/1)

Un pointeur null constante est une partie intégrante expression constante (5.19) rvalue de type entier qui prend la valeur de zéro.

C'est pourquoi, en C++, vous pouvez écrire

int* ptr = 0;

En C, cette règle est similaire, mais c'est un peu différent (§6.3.2.3/3):

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

Par conséquent, les deux

int* ptr = 0;

et

int* ptr = (void *)0

sont juridique. Cependant, je suppose que l' void* casting est ici de sorte que les déclarations comme

int x = NULL;

produire un avertissement du compilateur sur la plupart des systèmes. En C++, ce ne serait pas légal, car vous ne pouvez pas convertir implicitement un void* à un autre type de pointeur implicitement, sans plâtre. Par exemple, ce qui est illégal:

int* ptr = (void*)0; // Legal C, illegal C++

Cependant, cela conduit à des problèmes, car le code

int x = NULL;

est juridique C++. De ce fait, et la confusion qui s'ensuivit (et l'autre cas, montré plus tard), C++11 a maintenant un mot-clé nullptr représentant un pointeur null:

int* ptr = nullptr;

Cela n'a aucun des problèmes ci-dessus.

L'autre avantage de l' nullptr - dessus de 0, c'est qu'il joue mieux avec le C++ type de système. Par exemple, supposons que j'ai ces deux fonctions:

void DoSomething(int x);
void DoSomething(char* x);

Si je l'appelle

DoSomething(NULL);

C'est l'équivalent de

DoSomething(0);

qui demande DoSomething(int) à la place de l' DoSomething(char*). Cependant, avec nullptr, je pourrais écrire

DoSomething(nullptr);

Et il appelle l' DoSomething(char*) fonctionner comme prévu.

De même, supposons que j'ai un vector<Object*> et que vous voulez définir chaque élément d'être un pointeur null. À l'aide de l' std::fill algorithme, je pourrais essayer d'écrire

std::fill(v.begin(), v.end(), NULL);

Cependant, cela ne veut pas compiler, parce que le système de template de friandises NULL comme int et non pas un pointeur. Pour résoudre ce problème, j'aurais à écrire

std::fill(v.begin(), v.end(), (Object*)NULL);

C'est moche et un peu de défaites le but du système de template. Pour résoudre ce problème, je peux utiliser nullptr:

std::fill(v.begin(), v.end(), nullptr);

Et depuis nullptr est connu pour avoir un type correspondant à un pointeur null (plus précisément, std::nullptr_t), cela permettra de compiler correctement.

Espérons que cette aide!

17voto

Keith Thompson Points 85120

En C, NULL augmente à un définis par l'implémentation de pointeur null constante". Un pointeur null constante est un entier expression constante avec la valeur 0, ou une expression en fonte d' void*. Donc, C la mise en œuvre peut définir NULL comme 0 ou ((void*)0).

En C++, les règles de pointeur null constantes sont différentes. En particulier, ((void*)0) n'est pas une C++ pointeur null constante, donc une implémentation C++ ne peut pas définir NULL de cette façon.

-3voto

Kevin M Points 112

La raison pour laquelle C ++ utilise seulement 0 au lieu de (void*)0 est que vous pouvez définir un pointeur sur la fonction membre (MFP) sur NULL. Les types de MFP sont très stricts en termes de typage et ne peuvent pas être convertis (implicitement ou explicitement) en un type autre que les autres MFP de la même classe. Étant donné que (void*) n'est pas un type de MFP, l'attribution de (void*)0 à un MFP n'est pas autorisée.

Toute utilisation autre que celle utilisée avec les MFP semblerait autoriser parfaitement (void*)0 .

-6voto

Jay Points 6999

Le langage C a été créé pour faciliter le programme de microprocesseurs. Un C pointeur est utilisé pour stocker l'adresse de données dans la mémoire. Une voie a été nécessaire pour représenter qu'un pointeur n'avait aucune valeur valide. L'adresse zéro a été choisi car tous les microprocesseurs utilisés à cette adresse pour le démarrage. Puisqu'il ne pouvait pas être utilisé pour autre chose que zéro était un bon choix pour représenter un pointeur avec aucune valeur valide. C++ est compatible avec le C il est donc hérité de cette convention.

L'exigence de la coulée de zéro lorsqu'il est utilisé comme un pointeur n'est qu'un ajout récent. Plus tard, des générations de C voulu avoir plus de rigueur (et espérons-le, moins d'erreurs), de sorte qu'ils ont commencé à être plus pointilleux sur la syntaxe.

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