offsetof
来自cppreference.com
在标头 <cstddef> 定义 | ||
#define offsetof(type, member) /* 由实现定义 */ | ||
宏 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 缺陷报告 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; // 警告:'S' 不是标准布局类型}; int main(){std::cout<<"char m0 的偏移 = "<< offsetof(S, m0)<<'\n'<<"double m1 的偏移 = "<< offsetof(S, m1)<<'\n'<<"short m2 的偏移 = "<< offsetof(S, m2)<<'\n'<<"char m3 的偏移 = "<< offsetof(S, m3)<<'\n';}
可能的输出:
char m0 的偏移 = 0 double m1 的偏移 = 8 short m2 的偏移 = 16 char m3 的偏移 = 18
[编辑]缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
CWG 273 | C++98 | 重载了一元 operator& 时 offsetof 可能无法正常使用 | 即使重载了 operator& 也必须正常使用 |
LWG 306 | C++98 | 未指定在 type 不是 简旧数据类型(PODType) 的情况下的行为 | 此时结果未定义 |
LWG 449 | C++98 | LWG 问题 306 的解决方案移除了 offsetof 的其他要求 | 重新添加这些要求 |
[编辑]参阅
sizeof 运算符返回的无符号整数类型 (typedef) | |
(C++11) | 检查类型是否为标准布局类型 (类模板) |
offsetof 的 C 文档 |