分配后成为工会的活跃成员

cer*_*ka2 9 c++ undefined-behavior unions assignment-operator

假设sizeof( int ) == sizeof( float ),并且我有以下代码片段:

union U{
    int i;
    float f;
};

U u1, u2;
u1.i = 1;    //i is the active member of u1
u2.f = 1.0f; //f is the active member of u2

u1 = u2;
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 它有定义的行为吗?如果不是为什么?
  2. u1分配后的活跃成员是什么?为什么?
  3. u1赋值后可以读取 的哪个成员而不会导致 UB,为什么?

APr*_*mer 13

  1. 它有定义的行为吗?如果不是为什么?

它定义了行为。赋值复制了 的值u2,对我来说,联合体的值是活跃成员的指定(尽管该部分没有被代表,因此无法检查,但它确定什么是 UB,什么不是)以及 的值活跃成员(如果有的话)。

  1. 分配后 u1 的活跃成员是什么?为什么?

f,见上文。

赋值后可以读取 u1 的哪个成员而不会导致 UB,为什么?

F。一般来说,在 C++ 中,只有联合体的活动成员才能在没有 UB 的情况下被读取。结构体的联合有一个特殊的规则,其中这些结构体具有共同的初始序列。注意:C 更加宽松,并且使实现定义(并且可能完全定义)某些在 C++ 中未定义的情况,我可能错过了 C++ 中的一些更改,以使其与 C 更兼容。


如果有人想查找标准,我建议从class.copy.assign/13开始。

  • 请注意,许多 C++ 实现*确实*定义了读取非活动联合成员的行为。例如,所有实现 [GNU C 和 C++ 扩展](https://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit-fields-implementation.html) 的编译器,例如 GCC, clang,ICC 像 C99 一样定义它。ISO C++ 保留行为未定义并不会阻止实现定义它。GCC 通过引用 C89/C90 标准来描述它的方式似乎确实表明 C89 需要实现来选择某些行为,但这是古老的;现代 C 定义了它 (2认同)