Is it UB to reinterpret_cast the first union member to the type of the active union member?

Viewed 136

Given the code:

struct A { int i; };
struct B { std::string s; };

struct C
{
    union
    {
        A a{};
        B b;
    };
};

is the following access well defined:

void foo()
{
    C c;        // c.a is active
    c.b = {};   // now c.b is active

    auto& b = reinterpret_cast<B&>(c.a); // read c.b via access to c.a
    // use b somehow
}
1 Answers

According to cppreference in the "Notes" section, it is perfectly legal to reinterpret_cast a pointer to one member of a union to a pointer of the type of another member of the union.

Assuming that alignment requirements are met, a reinterpret_cast does not change the value of a pointer outside of a few limited cases dealing with pointer-interconvertible objects:

struct S1 { int a; } s1;
struct S2 { int a; private: int b; } s2; // not standard-layout
union U { int a; double b; } u = {0};
int arr[2];

int* p1 = reinterpret_cast<int*>(&s1); // value of p1 is "pointer to s1.a" because s1.a
                                   // and s1 are pointer-interconvertible

int* p2 = reinterpret_cast<int*>(&s2); // value of p2 is unchanged by reinterpret_cast and
                                   // is "pointer to s2". 

int* p3 = reinterpret_cast<int*>(&u);  // value of p3 is "pointer to u.a": u.a and u are
                                   // pointer-interconvertible

double* p4 = reinterpret_cast<double*>(p3); // value of p4 is "pointer to u.b": u.a and u.b
                                        // are pointer-interconvertible because both
                                        // are pointer-interconvertible with u

int* p5 = reinterpret_cast<int*>(&arr); // value of p5 is unchanged by reinterpret_cast and
                                    // is "pointer to arr"
Related