2016-07-27 1 views
2

Depuis de-référencement nullptr (NULL) est un comportement non défini à la fois dans C et C++, je me demande si l'expression &(*ptr) est valide si ptr est nullptr (NULL).C/C++ nullptr déréférencer

S'il s'agit également d'un comportement indéfini, comment fonctionne la macro OFFSETOF dans la réponse liée?

J'ai toujours pensé que ptr->field est un raccourci pour (*ptr).field

Je pense que la réponse à ma question est similaire en C et C++.

+3

Norme de projet C11 n1570: * 6.5.3.2 Opérateurs d'adresse et d'indirection 3 L'opérateur unaire & donne l'adresse de son opérande. Si l'opérande a le type '' type '', le résultat a le type '' pointer to type ''. Si l'opérande est le résultat d'un opérateur unaire *, ni cet opérateur ni l'opérateur & est évalué et le résultat est comme si les deux étaient omis, sauf que les contraintes sur les opérateurs s'appliquent toujours et le résultat n'est pas une valeur lvalue. * – EOF

+0

Je l'ai marqué en tant que doublon, mais assurez-vous de lire la discussion sous la réponse C++, ainsi que [cette discussion] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active .html # 232), car ce n'est pas tout à fait si explicite dans la norme C++. – TartanLlama

+2

Je doute que cela soit en double car OP demande "si déréférencement' nullptr' est UB comment offesetof fonctionne " – Slava

Répondre

2

TL; DR &(*(char*)0) est bien défini.

La norme C++ ne dit pas que l'indirection de null pointeur a UB. projet de norme actuelle, [expr.unary.op]

  1. L'opérateur unaire * effectue indirection: l'expression à laquelle il est appliqué est un pointeur sur un type d'objet, ou un pointeur vers un type de fonction et le résultat est une lvalue se référant à l'objet ou la fonction à laquelle l'expression pointe. Si le type de l'expression est "pointeur vers T", le type du résultat est "T". [snip]

  2. Le résultat de l'opérateur unaire & est un pointeur vers son opérande. L'opérande doit être une lvalue ou un id qualifié. [Snip]

Il n'y a pas à moins que le UB lvalue de l'expression de indirection est converti en un rvalue.


La norme C est beaucoup plus explicite. C11 du projet de norme §6.5.3.2

  1. L'opérateur unaire & donne l'adresse de son opérande. Si l'opérande a le type "type", le résultat a le type "pointer to type". Si l'opérande est le résultat d'un opérateur unaire *, ni l'opérateur & ni l'opérateur & ne sont évalués et le résultat est comme si les deux étaient omis, sauf que les contraintes sur les opérateurs s'appliquent toujours et que le résultat n'est pas une valeur lvalue. De même, si l'opérande est le résultat d'un opérateur [], ni l'opérateur & ni l'unaire * implicite par le [] n'est évalué et le résultat est comme si l'opérateur & était supprimé et l'opérateur [] a été modifié à un opérateur +. Sinon, le résultat est un pointeur vers l'objet ou la fonction désigné par son opérande.
1

Si elle est aussi un comportement non défini, comment offsetof travail?

Préférez utiliser the standard offsetof macro. Les versions développées localement entraînent des avertissements de compilateur.De plus:

offsetof est nécessaire pour travailler comme indiqué plus haut, même si unaire operator& est surchargée pour tous les types impliqués. Cela ne peut pas être implémenté en C++ standard et nécessite le support du compilateur.

offsetof est un built-in function in gcc.

+1

OP fait référence à la macro à partir du lien: #define OFFSETOF (type, champ) ((unsigned long) & ((((type *) 0) -> champ)) –

+0

@Byteventurer Aucune raison d'utiliser un 'cultivé' ' offsetoff', il en résulte des avertissements du compilateur. Utilisez la norme ['offsetof'] (http://en.cppreference.com/w/cpp/types/offsetof). –

+1

Je ne suis pas en train de propager l'utilisation de la macro, je suis en train d'expliquer ce à quoi l'OP se réfère en posant la question ... –