工会成员的 offsetof 总是零吗?

vit*_*aut 6 c++ union

C++ 是否保证offsetof(U, m)任何联合U及其成员总是返回零,m或者是否存在非零的情况?

union U {
  M m;
  ...
};
Run Code Online (Sandbox Code Playgroud)

yao*_*o99 6

是的,它总是零。 6.8.2.4

两个对象 a 和 b 在以下情况下是指针可转换的:
— 它们是同一个对象,或者
— 一个是联合对象,另一个是该对象的非静态数据成员 ([class.union]),或者
— 一个是一个标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的任何基类子对象 ([class.mem]),或
— 存在一个对象 c,使得 a 和 c 是指针可相互转换的,而 c 和 b 是指针可相互转换的。
如果两个对象是指针可互转换的,则它们具有相同的地址,并且可以通过 reinterpret_cast 从指向另一个的指针获取指向一个的指针。[注意:数组对象和它的第一个元素不是指针可相互转换的,即使它们具有相同的地址。— 尾注]

由于它们是指针可互换的并且共享相同的地址,因此offsetof(U, m)应该为零。

更新:

如果联合U不是标准布局,则它是有条件支持的。17.2.4.1

宏 offsetof(type, member-designator) 与 C 标准库头文件 <stddef.h> 中的相应宏具有相同的语义,但在本文档中接受一组受限制的类型参数。有条件地支持将 offsetof 宏与标准布局类 ([class.prop]) 以外的类型一起使用。 183 表达式 offsetof(type, member-designator) 从不依赖于类型,并且如果并且仅当类型依赖时。将 offsetof 宏应用于静态数据成员或函数成员的结果未定义。offsetof 宏调用的任何操作都不应引发异常,并且 noexcept(offsetof(type, member-designator)) 应为真。

但是一旦它被支持,唯一有意义的结果就是零,因为它们共享相同的地址。