Standardkonformer Hack
-
Arcoth schrieb:
Man darf nur keine lvalue-to-rvalue Konvertierung von a->f machen, solange ein B drin gespeichert ist, weil man dann strict-aliasing verletzen wuerde.
Doch, mMn. müsste das auch OK sein.
Und zwar in so einem Fall:a->x = 123; // Wir initialisieren ein A a->f = 42; b->x = 123; // Wir machen ne teilweise initialisierung eines B (ist ja erlaubt, auf b->d zuzugreifen hätte UB, aber das tu wir ja nicht) cout << a->f; // Wir lesen einfach einen float. Über einen A-Zeiger, aber das sollte egal sein (siehe unten)3.10.10
If a program attempts to access the stored value of an object through a glvalue of other than one of the
following types the behavior is undefined:
...
an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic
data members (including, recursively, an element or non-static data member of a subaggregate
or contained union),Man bemerke das "an". Da steht nicht dass es sich dabei um einen speziellen Aggregate-Type handeln muss.
Für mich heisst das: strict aliasing greift nur für non-aggregates, non-unions und atomare Typen.
Sämtliche Aggregate-Layer zwischen einem Zeiger/einer Referenz und dem atomaren Typ müssten dabei egal sein. Ich dürfte also auch über einen C-Zeiger auf den float zugreifen, wenn der float da drin den selben Offset hat.EDIT: Fehler korrigiert
ps:
Im Grund genommen würde das bedeuten dass es für UDT aggregates keinen "effective type" bzw. "dynamic type" gibt, sondern nur für die darin enthaltenen atomaren Member. Und dann wäre die Sache ganz einfach, dann geht es einfach um den atomaren Typ mit dem eine Speicherstelle das letzte mal geschrieben wurde.