Namespaces
Variants

offsetof

来自 zh.cppreference.net
 
 
 
类型支持
基本类型
定宽整数类型 (C++11)
定宽浮点类型 (C++23)
(C++11)    
(C++17)
数值极限
C 数值极限接口
运行时类型信息
 
定义于头文件 <cstddef>
#define offsetof(type, member) /* implementation-defined */

宏 offsetof 展开成一个类型为 std::size_t 的整数常量表达式,其值为从指定类型对象的起始位置到其指定子对象的偏移量(以字节为单位),包括任何填充位。

给定一个具有静态存储期的类型 o 的对象 type,o.member 应为引用 o 的子对象的左值常量表达式。否则,行为未定义。特别地,如果 member 是静态数据成员、位域或成员函数,则行为未定义。

如果 type 不是POD 类型(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 文档 关于 offsetof