在这个答案的评论中,有人说使用类似于联合体的方式将整数拆分成字节会导致未定义的行为。那里给出的代码与此相似,但并不完全相同,请注意我是否更改了与未定义行为相关的方面。
到目前为止,我认为这是一种很好的方法来处理像
这是未定义行为吗?如果是,为什么?(我不知道什么是“在C++中访问未活动的联合成员是UB”。)
union addr {
uint8_t addr8[4];
uint32_t addr32;
};
到目前为止,我认为这是一种很好的方法来处理像
addr = {127, 0, 0, 1};
这样的事情,并返回相应的 uint32_t
。(我认识到这可能会因为我的系统字节序的不同而产生不同的结果。但问题仍然存在。)这是未定义行为吗?如果是,为什么?(我不知道什么是“在C++中访问未活动的联合成员是UB”。)
C99
- 在这方面C99和C++03非常接近。
C++03
- 在一个联合体中,最多只能有一个数据成员处于活动状态,也就是说,在任何时候最多只能在联合体中存储一个数据成员的值。 C++03,第9.5节(1),第162页。
然而
- 如果POD-union包含多个共享公共初始序列的POD-structs[...],则允许检查任何POD-struct成员的共同初始序列 同上。
- 如果两个POD-struct[...]类型具有相同数量的非静态数据成员,并且对应的非静态数据成员(有序)具有布局兼容的类型,则它们是布局兼容的类型 C++03,第9.2节(14),第157页。
- 如果两种类型T1和T2是相同的类型,则T1和T2是布局兼容的类型。 C++03,第3.9节(11),第53页。
结论
- 由于
uint8_t[4]
和uint32_t
不是相同的类型(我猜测这和严格别名有关),而且两者都不是POD结构体/联合体,因此上述代码确实是未定义的行为?
C++11
- 请注意,聚合类型不包括联合类型,因为具有联合类型的对象只能同时包含一个成员。 C++11,脚注46,第42页