web-dev-qa-db-fra.com

La macro NULL peut-elle réellement être un nullptr?

Selon le projet de norme N4713 (7.11/1):

Une constante de pointeur nul est un littéral entier (5.13.2) de valeur zéro ou une valeur de type std::nullptr_t.

et 21.2.3/2:

La macro NULL est une constante de pointeur nul définie par l'implémentation.

suivez que NULL peut être défini comme nullptr. La même chose est mentionnée sur cppreference :

#define NULL 0
//since C++11
#define NULL nullptr

En même temps, la clause "Opérateurs additifs" dit (8.5.6/7):

Si la valeur 0 est ajouté ou soustrait d'une valeur de pointeur nulle, le résultat est une valeur de pointeur nulle. Si deux valeurs de pointeur nul sont soustraites, le résultat est égal à la valeur 0 converti en type std::ptrdiff_t.

Par conséquent, le code suivant doit être valide:

0 + nullptr; 
nullptr - nullptr; 

mais en raison du manque d'opérateurs +/- pour std::nullptr_t le le code n'est pas valide .

Y a-t-il quelque chose que je n'ai pas pris en compte ou la macro NULL ne peut pas être réellement définie comme nullptr?

41
αλεχολυτ

Alors que nullptr est une constante de pointeur nul , ce n'est pas une valeur de pointeur nul . Ce dernier est une valeur d'un type de pointeur, qui std::nullptr_t n'est pas.

Référence:

Une constante de pointeur nul est un littéral entier (5.13.2) de valeur zéro ou une valeur de type std::nullptr_t. ne constante de pointeur nul peut être convertie en un type de pointeur; le résultat est la valeur de pointeur nulle de ce type et se distingue de toutes les autres valeurs du pointeur d'objet ou du type de pointeur de fonction. Une telle conversion est appelée conversion de pointeur nul. [...]

7.11/1 dans N4659, accentuez le mien

Donc NULL peut en effet être nullptr sans fournir les opérateurs arithmétiques.

47
Baum mit Augen

nullptr est un littéral de pointeur nul, et bien que le résultat de la conversion de nullptr en type de pointeur soit la valeur du pointeur nul, nullptr lui-même n'est pas de type pointeur, mais de type std::nullptr_t. L'arithmétique fonctionne si vous convertissez le nullptr en un type de pointeur:

0 + (int*)nullptr; 
(int*)nullptr - (int*)nullptr;

La macro NULL peut-elle réellement être un nullptr?

Oui, car nullptr est un littéral de pointeur nul.

Notez qu'avant C++ 11, tous les littéraux de pointeur null en C++ se trouvaient également être des littéraux entiers, donc ce mauvais code: char c = NULL; avait l'habitude de travailler dans la pratique. Si NULL est défini comme nullptr, ce code ne fonctionne plus.

7
eerorika

De plus, soit les deux opérandes doivent avoir un type d'énumération arithmétique ou non étendue, ou un opérande doit être un pointeur vers un type d'objet complètement défini et l'autre doit avoir un type d'énumération intégral ou non étendu.

Pour la soustraction, l'un des éléments suivants doit être respecté:
(2.1) les deux opérandes ont un type d'énumération arithmétique ou non étendue; ou
(2.2) les deux opérandes sont des pointeurs vers des versions qualifiées cv ou non cv du même type d'objet complètement défini; ou
(2.3) l'opérande de gauche est un pointeur vers un type d'objet complètement défini et l'opérande de droite a un type d'énumération intégrale ou non.

std::nullptr_t n'en fait pas partie, donc std::nullptr ne peut pas participer aux opérations additives.

Notez que même toutes les valeurs de pointeur ne peuvent pas participer. Par exemple, les valeurs de pointeur de fonction et les valeurs de pointeur vide ne peuvent pas, même si l'une ou l'autre peut être une valeur de pointeur nulle.

6
n.m.

Le mot clé nullptr désigne le littéral du pointeur. Il s'agit d'un prvalue de type std::nullptr_t. Il existe des conversions implicites de nullptr en valeur de pointeur nulle de tout type de pointeur et de tout pointeur en type de membre. nullptr lui-même n'est pas une valeur de pointeur ni un pointeur. Les opérations arithmétiques ne sont donc pas applicables à nullptr.

5
S.M.