16

I have something like this:

union DataXYZ
{
    struct complex_t
    {
        float real, imag;
    } complex;

    struct vector_t
    {
        float magnitude, phase;
    } vector;
};

I have some vectors of these, being general-purpose workspace memory, where I use the fields accordingly after the semantic context.

I know it's undefined behaviour to read a field in a union, when the last active member was another field (and type?). Does this matter when the types and layout match exactly?

I've been commenting on some other similar questions, asking for references that guarantee the behaviour, but nothing came up yet - hence this question.

Shaggi
  • 1,121
  • 1
  • 9
  • 31

1 Answers1

15

Yes you can read the other member in this particular case.

This is what the C++11/14 standard has to say:

9.5 - Unions

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

But the note immediately after the section makes your particular instance legal since one special guarantee is made in order to simplify the use of unions:

[ Note: If a standard-layout union contains several standard-layout structs that share a common initial sequence (9.2), and if an object of this standard-layout union type contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of standard-layout struct members; see 9.2. —end note ]

And your structs do share a common initial sequence:

9.2.16 - Class members

The common initial sequence of two standard-layout struct (Clause 9) types is the longest sequence of non- static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities have layout-compatible types and either neither entity is a bit-field or both are bit-fields with the same width.

Holt
  • 36,600
  • 7
  • 92
  • 139
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 2
    The note immediately after the section you quoted makes this legal: " [Note: One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence (9.2), and if an object of this standard-layout union type contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of standard-layout struct members; see 9.2. —end note]" – Simple Jan 08 '16 at 12:54
  • Given this answer has zero score and the comments could get interesting, I'll wiki it. – Bathsheba Jan 08 '16 at 12:57
  • @Bathsheba 9.2.16 specify that the "initial sequence" is "the longest sequence [...] such that entites have layout compatible types [...].", so I think in this case it is the whole struct since `float` and `float` obvisouly have layout compatible types. – Holt Jan 08 '16 at 12:59
  • 1
    See [class.mem]/16: "The common initial sequence of two standard-layout struct (Clause 9) types is the longest sequence of non- static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that corresponding entities have layout-compatible types and either neither entity is a bit-field or both are bit-fields with the same width". `A` and `B` in the standard's example is the same as in the case above. – Simple Jan 08 '16 at 13:00
  • 1
    It seems strange that this guarantee is given in a note: notes are not normative. – Ruslan Sep 07 '17 at 16:09
  • @Ruslan: As the cross-reference suggests, the normative wording is in [class.mem]/19 (/25 in the current draft). – Davis Herring May 03 '19 at 03:18