在评论中这个答案 https://stackoverflow.com/a/8568531/1025391据说使用如下联合将整数分割成字节将是未定义的行为。该位置给出的代码与此相似但不完全相同,如果我更改了代码的未定义行为相关方面,请注明。
union addr {
uint8_t addr8[4];
uint32_t addr32;
};
到目前为止,我认为这将是做类似事情的好方法addr = {127, 0, 0, 1};
并得到对应的uint32_t
作为回报。 (我承认这可能会产生不同的结果,具体取决于我系统的字节顺序。但是问题仍然存在。)
这是未定义的行为吗?如果是这样,为什么? (我不知道什么意思C++中的UB是指访问不活跃的联合体成员。)
C99
C++03
-
在联合体中,任一时刻最多有一个数据成员处于活动状态,即任一时刻联合体中最多可以存储一个数据成员的值。C++03,第 9.5 节 (1),第 162 页
However
-
如果 POD 联合包含多个共享公共初始序列的 POD 结构 [...],则允许检查任何 POD 结构成员的公共初始序列 ibid.
-
如果两个 POD-struct [...] 类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(按顺序)具有布局兼容的类型,则它们是布局兼容的C++03,第 9.2 节 (14),第 157 页
-
如果两个类型 T1 和 T2 是同一类型,则 T1 和 T2 是布局兼容类型。C++03,第 3.9 节 (11),第 53 页
结论
- as
uint8_t[4]
and uint32_t
不是同一类型(我猜,a严格别名的事情 https://stackoverflow.com/a/99010/1025391)(加上两者都不是 POD-structs/union)上面确实是 UB?
C++11
-
请注意,聚合类型不包括联合类型,因为联合类型的对象一次只能包含一个成员。C++11,脚注 46,第 42 页
我不知道C++中的UB是什么意思,就是访问不活跃的联合成员。
基本上,这意味着您可以从联合中读取而不调用未定义行为的唯一成员是最后写入的成员。换句话说,如果您写信给addr32
,您只能读取addr32
, not addr8
反之亦然。
还提供了一个示例here https://stackoverflow.com/a/3071899/477878.
编辑:既然已经有很多讨论这是否是 UB,请考虑以下(完全有效的)C++11 示例;
union olle {
std::string str;
std::wstring wstr;
};
这里你肯定可以看到激活str和读取wstr可能是一个问题。您可以将此视为一个极端的示例,因为您甚至必须通过执行新的放置来激活成员,但规范实际上涵盖了这种情况,但没有提到它在其他方面被视为有关活动成员的特殊情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)