C++读取联合体同类型非活跃成员是否为UB?兼谈C标准差异
读取联合体非活跃成员是否属于C++未定义行为?
先看这段C++代码:
union A{ int a; int b; }; int main(){ A u = {.a = 0}; int r = u.b; // #1 这是未定义行为吗? }
C++标准下的判定
根据C++标准[class.union]条款:
在联合体中,非静态数据成员若其名称指代的对象生命周期已开始且未结束,则该成员是活跃的([basic.life])。联合体类型对象的非静态数据成员中,同一时间最多只能有一个处于活跃状态,也就是说,同一时间联合体中最多只能存储一个非静态数据成员的值。
本例中仅A::a为活跃成员,结合[basic.life]第7段的规定:
若出现以下情况,程序存在未定义行为:
- 使用左值访问该对象,或
#1处代码尝试读取生命周期尚未开始的u.b,按照C++标准,该操作属于未定义行为。
对标准要求的讨论
从实际使用角度看,这个要求确实偏严格——毕竟a和b都是int类型,内存布局完全一致,读取u.b本质就是读取与u.a相同的内存内容,逻辑上不会产生歧义。但C++标准从对象生命周期的维度做了严格约束,核心是为了维护类型系统的一致性,避免在更复杂的类型场景下出现类型安全问题。
C标准的差异
C标准对该场景的要求更为宽松,其文档中有明确说明:
若用于读取联合体对象内容的成员,与最后用于向该对象存储值的成员不同,则会将值的对象表示的对应部分重新解释为新类型的对象表示(该过程有时被称为类型双关)。这可能会得到非值表示。
也就是说,C标准明确允许这种跨成员读取的操作,仅要求按对象表示重新解释类型即可,不存在未定义行为。而C与C的这一差异,并未在C标准差异文档中被明确指出。
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

