首页 > 解决方案 > UB是否将第一个联合成员重新解释为活动联合成员的类型?

问题描述

给定代码:

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

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

以下访问是否定义良好:

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
}

标签: c++language-lawyerc++20

解决方案


根据“注释”部分中的cppreference,将指向联合的一个成员的指针重新解释为联合的另一个成员的类型的指针是完全合法的。

假设满足对齐要求,则 reinterpret_cast 不会更改指针的值,但处理指针可互转换对象的一些有限情况除外:

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"

推荐阅读