C++14中访问union的非活跃成员是否合法?
C++14中访问union非活跃成员的合法性问题
我查阅了大量资料后,对C14里访问union的非活跃成员是否合法感到困惑。我知道在C11及更早版本中,这属于未定义行为。
请问是否允许像以下代码这样使用union?
typedef union _BYTE_VAL_T { unsigned char Val; struct { unsigned char b0:1; unsigned char b1:1; unsigned char b2:1; unsigned char b3:1; unsigned char b4:1; unsigned char b5:1; unsigned char b6:1; unsigned char b7:1; } bits; } BYTE_BITS_T; int main() { BYTE_BITS_T reg; reg.bits.b5 = 0x1; std::cout << reg.Val; // use of inactive member }
解答
C++14标准层面的规则
C14确实新增了“union的所有非静态数据成员地址相同”的规定,但这一规则并未直接授权访问非活跃成员。从标准的严格定义来看,C14中访问union的非活跃成员仍然属于未定义行为——直到C++17才补充了更宽松的规则:若union的两个成员为标准布局类型,且它们的共同初始子序列覆盖整个成员,则允许通过一个成员赋值后访问另一个成员的对应部分。代码中的具体问题
- 代码里的位域结构体属于实现定义行为:位域的排列顺序(比如
b0对应字节的最低位还是最高位)、填充方式都由编译器决定,跨平台可能出现不一致的结果。 - 虽然主流编译器(GCC、Clang、MSVC)大多支持这种“类型双关”的union用法,将其作为编译器扩展,但这并非C++14标准所保证的合法行为。
- 总结
从标准规范角度,C++14中你的代码写法不合法;但从实际工程角度,多数编译器会支持该写法,不过需要承担位域布局带来的跨平台风险。
内容的提问来源于stack exchange,提问作者Manuel Tonella
相关产品推荐
相关产品推荐

