La norme mandat une lvalue-à-rvalue conversion du pointeur de la variable lors de l'application d'indirection?

StackOverflow https://stackoverflow.com//questions/21053273

Question

TL;DR

Étant donné le code suivant:

int* ptr;
*ptr = 0;

n' *ptr besoin d'un lvalue-à-rvalue la conversion de ptr avant d'appliquer indirection?

La norme couvre le sujet de lvalue-à-rvalue dans de nombreux endroits, mais ne semble pas préciser suffisamment d'informations pour déterminer si l' * l'opérateur exiger une telle conversion.

Détails

L' lvalue-à-rvalue la conversion est couvert dans N3485 dans la section 4.1 Lvalue-à-rvalue de conversion paragraphe 1 et dit (l'accent de la mine d'aller de l'avant):

Un glvalue (3.10) d'un non-fonctionnement, non-tableau de type T peut être converti pour un prvalue.53 Si T est un type incomplète, un programme qui nécessite cette conversion est mal formé.Si l'objet pour lequel la glvalue se réfère n'est pas un objet de type T et n'est pas un objet d'un type dérivé à partir de T, ou si l'objet est non initialisée, un programme que nécessite cette conversion a un comportement indéfini.[...]

Donc, ne *ptr = 0; nécessitent cette conversion?

Si nous allons à l'article 4 paragraphe 1 il dit:

[...]D'une conversion standard de séquence sera appliquée à une expression si nécessaire pour convertir un type de destination.

Alors, quand est-il nécessaire?Si l'on regarde l'article 5 Les Expressions l' lvalue-à-rvalue la conversion est mentionné dans le paragraphe 9 qui dit:

Chaque fois qu'un glvalue expression apparaît comme un opérande d'un opérateur qui s'attend à un prvalue pour que opérande, la lvalue-à-rvalue (4.1), tableau de pointeur (4.2), ou de la fonction de pointeur (4.3) standard les conversions sont appliqués à convertir l'expression d'un prvalue.[...]

et de l'alinéa 11 qui dit:

Dans certains contextes, l'expression n'apparaît que pour ses effets secondaires.Une telle expression est appelé un jeté de la valeur de l'expression.[...] L' lvalue-à-rvalue de conversion (4.1) s'applique si et seulement si le l'expression est une lvalue de la volatilité des qualifiés de type et il est l'un des la suite [...]

ni le paragraphe semble s'appliquer à cet exemple de code et 5.3.1 Les opérateurs unaires paragraphe 1 il dit:

Unaire * opérateur effectue indirection:l'expression à laquelle il est demandé doit être 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 pour laquelle l'expression de points.Si le type de l'expression est “pointeur de T,” le type du résultat est “T.” [ Note:indirection par le biais d'un pointeur vers un type incomplète (autres que les cv void) est valide.La lvalue ainsi obtenu peut être utilisé de façon limitée (pour initialiser un de référence, par exemple);cette lvalue ne doit pas être converti en prvalue, voir 4.1.—la note de fin ]

il ne semble pas exiger de l' valeur de le pointeur et je ne vois pas toutes les exigences pour un conversion d'un pointeur ici, ai-je raté quelque chose?

Pourquoi faisons-nous des soins?

J'ai vu une réponse et commentaires dans d'autres questions qui demande l'utilisation d'un pointeur non initialisé est un comportement indéfini, en raison de la nécessité d'une lvalue-à-rvalue la conversion de ptr avant d'appliquer l'indirection.Par exemple: Où, exactement, est-ce que C++ standard de dire déréférencement d'un pointeur non initialisé est un comportement indéfini? fait à cet argument, et je ne peux pas concilier l'argument avec ce qui est disposé dans l'un des récents projets de versions de la norme.Depuis que j'ai vu cela plusieurs fois, j'ai voulu obtenir des précisions.

La véritable preuve d'un comportement indéfini n'est pas aussi important puisque comme je l'ai noté dans la question ci-dessus, nous avons d'autres façon d'obtenir un comportement indéfini.

Était-ce utile?

La solution 2

J'ai converti la section mise à jour dans ma question, d'une réponse, puisqu'à ce stade, il semble être la réponse, mais satisfaisant dans l'un que ma question est sans réponse:

dpj m'a signalé deux threads qui couvrent très similaire au sol:

Le consensus semble être que la norme est mauvais spécifié et, par conséquent, ne peut pas fournir la réponse, je suis à la recherche d', Joseph Mansfield publié un rapport de défaut sur ce manque de précision, et on dirait qu'il est encore ouvert et il n'est pas évident quand il peut être précisé.

Il y a quelques arguments de bon sens quant à l' l'intention de la norme.On peut dire Logicially, un opérande est un prvalue si l'opération nécessite l'aide de la valeur de l'opérande.Un autre argument est que si nous regardons en arrière à la Projet de norme C99 dit une lvalue à rvalue la conversion est effectuée par défaut et les exceptions sont notées.La section pertinente du projet de standard C99 est 6.3.2.1 Lvalues, les tableaux et les pointeurs de fonction paragraphe 2 qui dit:

Sauf quand c'est l'opérande de l'opérateur sizeof, le unaire & de l'opérateur, l'opérateur++, l'-opérateur, ou l'opérande gauche de l' .opérateur ou un opérateur d'affectation, une lvalue qui n'a pas de type tableau est converti à la valeur stockée dans l'objet désigné (et n'est plus une lvalue).[...]

qui dit en substance, à quelques exceptions près d'un opérande est converti à la valeur stockée et depuis indirection n'est pas une exception, si cela est précisé également le cas dans C++ ainsi, alors il aurait en effet faire la réponse à ma question oui.

Comme j'ai tenté de clarifier la preuve d'un comportement indéfini était moins important que le fait de décider si une lvalue-à-rvalue de conversion est obligatoire.Si nous voulons prouver un comportement indéfini, nous avons d'autres approches.Jerry est un sens commun et indirection exige que l'expression être un pointeur vers un objet ou une fonction et d'une durée indéterminée valeur que par accident point à un objet valide. En général, le projet de norme C++ ne permet pas de donner une description explicite-à-dire en utilisant une période indéterminée, la valeur est undefined, à la différence de l'avant-projet de norme C99 En C++11 et le dos de la norme ne donne pas une description explicite-à-dire en utilisant une période indéterminée, la valeur est undefined.L'exception étant les itérateurs et, par extension, des pointeurs, nous avons le concept de valeur singulière et on nous dit dans l'article 24.2.1 que:

[...][ Exemple:Après la déclaration d'un pointeur non initialisé x (comme avec int* x;), x doit toujours être considéré comme une valeur singulière d'un pointeur.fin de l'exemple ] [...] Dereferenceable valeurs sont toujours non-singulière.

et:

Une défaillance de itérateur est un itérateur qui peut être au singulier.268

et la note de bas de page 268 dit:

Cette définition s'applique à des pointeurs, puisque les pointeurs sont des itérateurs.L'effet de déréférencement d'un itérateur, qui a été invalidé est pas défini.

En C++1y les changements de langue, et nous avons une déclaration explicite ce qui rend l'utilisation d'un intermédiaire de valeur est undefined, à quelques exceptions près.

Autres conseils

Je pense que vous vous approchez de ce à partir d'un plutôt angle oblique, pour ainsi dire.Selon le §5.3.1/1:

Unaire * l'opérateur effectue indirection:l'expression à laquelle il est appliqué doit être 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 d'où l'expression de points.Si le type de l'expression est “pointeur de T,” le type du résultat est “T.”

Bien que cela ne parle pas de la lvalue-à-rvalue de conversion, il faut que cette expression soit un pointeur vers un objet ou une fonction.Un pointeur non initialisé ne va pas (sauf, peut-être par hasard) une telle chose si la tentative de déréférencement donne un comportement indéfini.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top