offsetof
来自 cppreference.com
定义在头文件 <cstddef> 中 |
||
#define offsetof(type, member) /* implementation-defined */ |
||
宏 offsetof 展开为一个类型为 std::size_t 的整型常量表达式,其值为从指定类型对象的开头到其指定子对象的偏移量(以字节为单位),包括任何填充位。
给定一个类型为 type
且具有静态存储期的对象 o,o.member 应为一个指向 o 的子对象的左值常量表达式。否则,行为未定义。特别地,如果 member
是一个 静态数据成员、位域 或 成员函数,则行为未定义。
如果 type
不是一个 PODType(直到 C++11)标准布局 类型(从 C++11 开始),offsetof
的结果未定义(直到 C++17)使用 offsetof
宏是有条件支持的(从 C++17 开始).
表达式 offsetof(type, member) 从来不会 类型相关,并且当且仅当 type
相关时,它才与值相关。
内容 |
[编辑] 异常
offsetof
不抛出任何异常。
表达式 noexcept(offsetof(type, member)) 始终计算为 true. |
(自 C++11 起) |
[编辑] 注意
标准布局类型的第一个成员的偏移量始终为零 (空基优化 是强制性的)。 |
(自 C++11 起) |
offsetof
无法在标准 C++ 中实现,需要编译器支持:GCC,LLVM.
member
不限于直接成员。它可以表示给定成员的子对象,例如数组成员的元素。这由 C DR 496 指定。
C23 中规定,在 offsetof
中定义包含未加括号的逗号的新类型是未定义的行为,这种用法通常不受 C++ 模式下实现的支持:offsetof(struct Foo { int a, b; }, a) 被所有已知实现拒绝。
[编辑] 示例
运行此代码
#include <cstddef> #include <iostream> struct S { char m0; double m1; short m2; char m3; // private: int z; // warning: 'S' is a non-standard-layout type }; int main() { std::cout << "offset of char m0 = " << offsetof(S, m0) << '\n' << "offset of double m1 = " << offsetof(S, m1) << '\n' << "offset of short m2 = " << offsetof(S, m2) << '\n' << "offset of char m3 = " << offsetof(S, m3) << '\n'; }
可能的输出
offset of char m0 = 0 offset of double m1 = 8 offset of short m2 = 16 offset of char m3 = 18
[编辑] 缺陷报告
以下行为变更缺陷报告已追溯应用于之前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
CWG 273 | C++98 | 如果一元 operator& 被重载,则 offsetof 可能无法正常工作 |
即使 operator& 被重载,也需要正常工作如果 operator& 被重载 |
LWG 306 | C++98 | 当 type 不是 PODType 时,行为未指定 |
在这种情况下,结果是未定义的 |
LWG 449 | C++98 | offsetof 的其他要求被通过 LWG 问题 306 的解决方案删除 |
将它们添加回来 |
[编辑] 另请参阅
由 sizeof 运算符返回的无符号整数类型 (typedef) | |
(C++11) |
检查类型是否为 标准布局 类型 (类模板) |
C 文档 用于 offsetof
|