union A{
int a;
int b;
};
int main(){
A u = {.a = 0};
int r = u.b; // #1 Is this UB?
}
[class.union] sagt
In einer Union ist ein nicht statisches Datenelement aktiv, wenn sein Name auf ein Objekt verweist, dessen Lebensdauer begonnen und noch nicht beendet ist ([basic.life]). Höchstens eines der nicht statischen Datenelemente eines Objekts vom Typ Union kann jederzeit aktiv sein, d. h. der Wert von höchstens einem der nicht statischen Datenelemente kann jederzeit in einer Union gespeichert werden.
Nur in diesem Beispiel A::a
ist also aktiv [basic.life] p7 sagt
Das Programm weist undefiniertes Verhalten auf, wenn:
- Der GL-Wert wird verwendet, um auf das Objekt zuzugreifen, oder
#1
versucht, auf das Objekt zuzugreifen, dessen Lebensdauer noch nicht begonnen hat. Verursacht dieser Zugriff UB? Wenn ja, ist diese Anforderung zu restriktiv?
Übrigens: Stellt der C-Standard in diesem Beispiel die gleichen Anforderungen? Oder hat C in diesem Fall eine lockerere Anforderung?
Aktualisieren
In C-Standardfinde ich eine Notiz, die besagt
Wenn das Mitglied, das zum Lesen des Inhalts eines Union-Objekts verwendet wird, nicht mit dem Mitglied übereinstimmt, das zuletzt zum Speichern eines Werts im Objekt verwendet wurde, wird der entsprechende Teil der Objektdarstellung des Werts wie beschrieben als Objektdarstellung im neuen Typ neu interpretiert in 6.2.6 (ein Prozess, der manchmal als Type Punning bezeichnet wird). Dies könnte eine Darstellung ohne Wert sein.
Dies bedeutet, dass es in C zulässig ist. https://eel.is/c++draft/diff.iso
Unterabschnitt [diff.iso] listet die Unterschiede zwischen C++ und ISO C zusätzlich zu den oben aufgeführten Kapiteln dieses Dokuments auf.
weist nicht auf den Unterschied hin.
@463035818_is_not_a_number Nein, das ist nicht dasselbe. Der formale Wortlaut lautet [[class.mem.general] S.26](eel.is/c++draft/class.mem#general-26), Voraussetzung ist, dass diese beiden Varianten vom Strukturtyp sein sollten. Darüber hinaus bezieht sich das Konzept der „gemeinsamen Anfangssequenz“ auf eine „Standard-Layout-Struktur“.
– xmh0511
24. Mai um 12:32 Uhr
@NathanOliver Siehe eel.is/c++draft/basic.life#1werden Sie feststellen, wie die Lebensdauer einer Variante einer Union beginnt (im Zitat „nur“ hervorgehoben).
– xmh0511
24. Mai um 12:48 Uhr
[diff.iso] ist informativ und nicht normativ, daher ist das Weglassen eines Unterschieds zwischen C und C++ vermutlich ein Versehen und keine maßgebliche Aussage. Selbst wenn es normativ wäre, wäre es nur für C++ maßgebend und hätte keine Autorität über den C-Standard.
– Eric Postpischil
24. Mai um 13:14 Uhr
Ich denke, das ist immer noch größtenteils richtig, stackoverflow.com/questions/25664848/unions-and-type-punning, also vielleicht ein Duplikat.
– Lundin
24. Mai um 13:36 Uhr
Ok, da Sie die Frage im Wesentlichen selbst beantwortet haben, schließe ich als Betrüger, es sei denn, jemand hat neue Informationen zu den C23-C++23-Versionen …? Normativer Text in C++ ist das Zitat „Höchstens eines der nichtstatischen Datenelemente eines Objekts vom Unionstyp kann jederzeit aktiv sein“, normativer Text in C ist 6.5.2.3 „Ein Postfix-Ausdruck, gefolgt vom .-Operator und.“ Ein Bezeichner bezeichnet ein Mitglied einer Struktur oder eines Unionsobjekts. Der Wert ist der des benannten Mitglieds“ (die zitierte Fußnote verweist auf diesen Text). Und [diff.iso] ist gänzlich abzulehnen.
– Lundin
24. Mai um 14:21 Uhr