offsetof宏仅适用于标准布局类型,要求无虚函数/虚基类、成员访问控制一致、无位域且仅支持直接成员;返回size_t字节偏移,是编译期常量,不可用于静态成员或嵌套路径。
非标准布局类(比如含虚函数、多重继承、非公有继承、含非静态成员函数)无法用 offsetof 获取成员偏移,编译器会报错或行为未定义。标准布局要求:所有非静态数据成员同为公有/私有/保护;无虚函数、无虚基类;首个非静态成员与类起始地址对齐(即无前置 padding)。
实操建议:
static_assert(std::is_standard_layout_v, "must be standard layout"); 在编译期兜底std::string、std::vector 等非 POD 类型,仍可使用 offsetof——只要它们本身是标准布局(C++11 起,标准库容器满足该条件)offsetof,GCC/Clang 会拒绝,MSVC 可能返回 0 但不可靠offsetof 不支持嵌套路径,比如 offsetof(Outer, inner.member) 是非法的。它只接受一个类类型和该类**直接声明**的非静态数据成员名。
常见错误现象:
error: 'inner.member' is not a member of 'Outer'正确写法示例:
#includestruct Point { int x; float y; char z; }; // ✅ 正确:x、y、z 都是 Point 的直接成员 size_t off_x = offsetof(Point, x); // 0 size_t off_y = offsetof(Point, y); // 4(假设 int=4, float=4, 无 padding) size_t off_z = offsetof(Point, z); // 8
offsetof 返回 size_t,表示该成员相对于对象首地址的字节数。它不依赖实例,是纯编译期常量表达式(C++17 起),可用于 constexpr 上下文。
性能与兼容性影响:
C

offsetof。所谓“获取所有成员变量偏移量”必须显式列出每个成员。
实操建议:
p &((MyClass*)0)->member 查看偏移(本质就是 offsetof 的运行时验证)容易被忽略的一点:即使你把所有 offsetof 写全了,如果类定义后续加了新成员、调整了顺序或修改了访问控制,偏移列表就立刻失效——它不具备自同步能力。