Schreibt der Standard bei der Anwendung der Indirektion eine L-Wert-zu-R-Wert-Konvertierung der Zeigervariablen vor?

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

Frage

TL;DR

Angesichts des folgenden Codes:

int* ptr;
*ptr = 0;

tut *ptr erfordern eine L-Wert-zu-R-Wert Umwandlung von ptr bevor Sie die Indirektion anwenden?

Die Norm behandelt das Thema L-Wert-zu-R-Wert an vielen Stellen scheint jedoch nicht genügend Informationen anzugeben, um festzustellen, ob die * Operator erfordern einen solchen Umbau.

Einzelheiten

Der L-Wert-zu-R-Wert Die Konvertierung ist abgedeckt N3485 im Abschnitt 4.1 L-Wert-zu-R-Wert-Konvertierung Absatz 1 und sagt (Meine Betonung liegt auf der Zukunft):

Ein Glvalue (3.10) einer Nicht-Funktion, Nicht-Array-Typ T kann in ein PrValue umgewandelt werden.53 Wenn T ein unvollständiger Typ ist, ist ein Programm, das diese Konvertierung erfordert, schlecht geformt.Wenn das Objekt, auf das sich der Glvalue bezieht oder wenn das Objekt nicht initialisiert ist, hat ein Programm, das diese Konvertierung erfordert.[...]

Das gilt auch *ptr = 0; machen diesen Umbau notwendig?

Wenn wir zum Abschnitt gehen 4 Absatz 1 es sagt:

[...]Eine Standardkonvertierungssequenz wird auf einen Ausdruck angewendet Falls benötigt um es in einen erforderlichen Zieltyp zu konvertieren.

Wann ist es also? notwendig?Wenn wir uns den Abschnitt ansehen 5 Ausdrücke Die L-Wert-zu-R-Wert Die Konvertierung wird im Absatz erwähnt 9 was sagt:

Immer wenn ein Glvalue-Ausdruck als Operand eines Bedieners erscheint, der einen Prorue für diesen Operanden, die LVALUE-TO-RVALUE (4.1), Array-to-Pointer (4.2) oder Funktionen zu Objekte (4.3) erwartet, sind Standardkonvertierungen angewendet, um den Ausdruck in einen PrValue umzuwandeln.[...]

und Absatz 11 was sagt:

In manchen Kontexten erscheint ein Ausdruck nur wegen seiner Nebenwirkungen.Ein solcher Ausdruck wird als Ausdruck des Wertwerts bezeichnet. [...] Die Lvalue-to-Rele-Umwandlung (4.1) wird nur dann angewendet, wenn der Ausdruck ein LVALUE des volatil-qualifizierten Typs ist, und es ist einer der folgenden [ ...

Keiner der Absätze scheint auf dieses Codebeispiel zuzutreffen und 5.3.1 Unäre Operatoren Absatz 1 es sagt:

Der unäre *-Operator führt eine Indirektion aus:Der Ausdruck, auf den er angewendet wird, muss ein Zeiger auf einen Objekttyp oder ein Zeiger auf einen Funktionstyp sein. Das Ergebnis ist ein LVALUE, der sich auf das Objekt oder die Funktion bezieht, auf die sich der Ausdruck Punkte Punkte bezieht.Wenn der Typ des Ausdrucks "Zeiger auf T" ist, lautet der Typ des Ergebniss "T". [ Notiz:Die Indirektion durch einen Zeiger auf einen unvollständigen Typ (außer CV -Void) ist gültig.Der so erhaltene Lvalue kann in begrenzter Weise verwendet werden (z. B. eine Referenz initialisieren);Dieser Lvalue darf nicht in ein Prvalue umgewandelt werden, siehe 4.1.—Endnote]

es scheint das nicht zu erfordern Wert des Zeigers und ich sehe keine Anforderungen für eine Konvertierung des Zeigers. Übersehe ich hier etwas?

Warum kümmert es uns?

Ich habe in anderen Fragen eine Antwort und Kommentare gesehen, die behaupten, dass die Verwendung eines nicht initialisierten Zeigers aufgrund der Notwendigkeit eines undefinierten Verhaltens sei L-Wert-zu-R-Wert Umwandlung von ptr bevor Sie die Indirektion anwenden.Zum Beispiel: Wo genau sagt der C++-Standard, dass die Dereferenzierung eines nicht initialisierten Zeigers ein undefiniertes Verhalten ist? bringt dieses Argument vor und ich kann das Argument nicht mit dem in Einklang bringen, was in einer der jüngsten Entwurfsversionen des Standards dargelegt wird.Da ich das schon mehrmals gesehen habe, wollte ich es klären.

Der eigentliche Beweis für undefiniertes Verhalten ist nicht so wichtig, da wir, wie ich in der oben verlinkten Frage angemerkt habe, andere Möglichkeiten haben, zu undefiniertem Verhalten zu gelangen.

War es hilfreich?

Lösung 2

Ich habe den Update-Abschnitt in meiner Frage in eine Antwort umgewandelt, da dies an dieser Stelle die Antwort zu sein scheint, wenn auch unbefriedigend, sodass meine Frage nicht beantwortet werden kann:

dyp hat mich auf zwei relevante Threads hingewiesen, die sehr ähnliche Themen behandeln:

Der Konsens scheint zu sein, dass dies der Standard ist schlecht spezifiziert und kann daher nicht die Antwort geben, die ich suche, Joseph Mansfield Ich habe einen Fehlerbericht zu diesem Mangel an Spezifikation veröffentlicht, und es sieht so aus, als wäre es still offen und es ist nicht klar, wann es geklärt werden kann.

Es gibt ein paar vernünftige Argumente dafür Absicht des Standards.Man kann darüber streiten Logischerweise ist ein Operand ein Wert, wenn die Operation die Verwendung des Werts dieses Operanden erfordert.Ein weiteres Argument ist, dass, wenn wir zurückblicken C99-Standardentwurf sagt Standardmäßig erfolgt eine L-Wert-zu-R-Wert-Konvertierung und die Ausnahmen werden vermerkt.Der relevante Abschnitt aus dem Entwurf des C99-Standards lautet 6.3.2.1 L-Werte, Arrays und Funktionsbezeichner Absatz 2 was sagt:

Außer wenn es sich um den Operanden des sizeof-Operators, des unären &-Operators, des ++-Operators, des ---Operators oder des linken Operanden von handelt.Operator oder Zuordnungsoperator, ein LVALUE, der kein Array -Typ hat, wird in den im angegebenen Objekt gespeicherten Wert umgewandelt (und ist kein LVALUE mehr).[…]

was im Grunde mit einigen Ausnahmen einen Operanden besagt wird in den gespeicherten Wert umgewandelt und da Indirektion ist keine Ausnahme, wenn klargestellt wird, dass dies auch der Fall ist C++ Dann wäre das tatsächlich die Antwort auf meine Frage Ja.

Als ich zu klären versuchte, war der Nachweis undefinierten Verhaltens weniger wichtig als die Klärung, ob eine L-Wert-zu-R-Wert-Konvertierung vorgeschrieben ist.Wenn wir undefiniertes Verhalten nachweisen wollen, haben wir alternative Ansätze.Jerrys Ansatz ist insofern ein vernünftiger Ansatz Indirektion erfordert, dass der Ausdruck ein Zeiger auf ein Objekt oder eine Funktion ist und ein unbestimmter Wert nur zufällig auf ein gültiges Objekt zeigt. Im Allgemeinen gibt der C++-Standardentwurf im Gegensatz zum C99-Standardentwurf keine explizite Aussage dazu, dass die Verwendung eines unbestimmten Werts undefiniert ist In C++11 und älter gibt der Standard keine explizite Aussage, dass die Verwendung eines unbestimmten Werts undefiniert ist.Die Ausnahme bilden Iteratoren und als Erweiterung Zeiger haben wir das Konzept von singulärer Wert und es wird uns im Abschnitt erzählt 24.2.1 Das:

[…][ Beispiel:Nach der Deklaration eines nicht initialisierten Zeigers x (wie bei int* x;) muss immer davon ausgegangen werden, dass x einen singulären Wert eines Zeigers hat.—Beispiel beenden] […] Dereferenzierbare Werte sind immer nicht singulär.

Und:

Ein ungültiger Iterator ist ein Iterator, der singulär sein kann.268

und in Fußnote 268 heißt es:

Diese Definition gilt für Zeiger, da Zeiger Iteratoren sind.Die Auswirkung der Dereferenzierung eines ungültig gemachten Iterators ist undefiniert.

In C++1 Jahr Die Sprache ändert sich und wir haben eine explizite Anweisung, die die Verwendung eines Zwischenwerts mit einigen wenigen Ausnahmen undefiniert macht.

Andere Tipps

Ich glaube, Sie gehen das sozusagen aus einem eher schrägen Blickwinkel an.Gemäß §5.3.1/1:

Das Unäre * Betreiber ausführt Indirektion:Der Ausdruck, auf den er angewendet wird, muss ein Zeiger auf einen Objekttyp oder ein Zeiger auf einen Funktionstyp sein. Das Ergebnis ist ein LVALUE, der sich auf das Objekt oder die Funktion bezieht, auf die sich der Ausdruck Punkte Punkte bezieht.Wenn der Typ des Ausdrucks „Zeiger auf T“ ist, ist der Typ des Ergebnisses „T“.

Obwohl es hier nicht um die L-Wert-zu-R-Wert-Konvertierung geht, erfordert es, dass der Ausdruck ein Zeiger auf ein Objekt oder eine Funktion ist.Ein nicht initialisierter Zeiger ist so etwas nicht (außer vielleicht aus Versehen), daher führt der Versuch der Dereferenzierung zu undefiniertem Verhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top