Accessing same-type inactive member in unions
Asked Answered
C

1

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.

Conjugate answered 8/1, 2016 at 12:39 Comment(4)
Possible duplicate of C++ Undefined behaviour with unionsSurtout
Not a good duplicate. There's no standard ref.Apophasis
This is actually legal.Barbera
Related: #26560811 (but the answer bellow has more references).Overcompensation
A
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.

Apophasis answered 8/1, 2016 at 12:39 Comment(6)
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]"Barbera
Given this answer has zero score and the comments could get interesting, I'll wiki it.Apophasis
@Apophasis 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.Overcompensation
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.Barbera
It seems strange that this guarantee is given in a note: notes are not normative.Arleenarlen
@Ruslan: As the cross-reference suggests, the normative wording is in [class.mem]/19 (/25 in the current draft).Meloniemelony

© 2022 - 2024 — McMap. All rights reserved.