offsetof
|
定义于头文件
<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 。 |
(since C++11) |
注释
|
标准布局类型首个成员的偏移量始终为零( 空基类优化 是强制性的)。 |
(since 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++标准。
| 缺陷报告 | 适用标准 | 发布时行为 | 正确行为 |
|---|---|---|---|
| CWG 273 | C++98 |
offsetof
在重载一元
operator&
时可能失效
|
要求即使重载
operator&
也能正常工作
|
| LWG 306 | C++98 |
未规定当
type
不是
PODType
时的行为
|
此情况下结果为未定义 |
| LWG 449 | C++98 |
offsetof
的其他要求因
LWG 306 的解决方案被移除 |
重新添加这些要求 |
参见
|
sizeof
运算符返回的无符号整数类型
(类型别名) |
|
|
(C++11)
|
检查类型是否为
标准布局
类型
(类模板) |
|
C 文档
关于
offsetof
|
|