offsetof (C++11 <cstddef>)#include <cstddef>
struct Foo { char c; int i; double d; };
size_t off_i = offsetof(Foo, i); // 標準、可攜、編譯期常數
// 經典實現 (GCC/MSVC 內建通常更安全) #define offsetof(type, member) ((size_t)&(((type*)0)->member)) // MSVC 64 位元加強版 (處理虛繼承等複雜情況) #ifdef _WIN64 #define offsetof(s,m) (size_t)( (ptrdiff_t)&reinterpret_cast((((s*)0)->m)) ) #else #define offsetof(s,m) (size_t)&(((s*)0)->m) #endif
核心技巧:將 0 轉為 type*,存取 member,取其位址 → 即為相對於結構體起始的位元組偏移。未定義行為警告:解參考空指標屬 UB,但編譯器對此模式有特殊處理,實際不產生指令。
#include <iostream>
#include <cstddef>
using namespace std;
struct AlignDemo {
char c; // offset 0, size 1
char b; // offset 1, size 1
// padding 2 bytes (對齊到 4)
int e; // offset 4, size 4
int e1; // offset 8, size 4
// padding 4 bytes (對齊到 8)
double d; // offset 16, size 8
}; // sizeof = 24
int main() {
cout << "offsetof(c) = " << offsetof(AlignDemo, c) << '\n'; // 0
cout << "offsetof(b) = " << offsetof(AlignDemo, b) << '\n'; // 1
cout << "offsetof(e) = " << offsetof(AlignDemo, e) << '\n'; // 4
cout << "offsetof(e1) = " << offsetof(AlignDemo, e1) << '\n'; // 8
cout << "offsetof(d) = " << offsetof(AlignDemo, d) << '\n'; // 16
cout << "sizeof = " << sizeof(AlignDemo) << '\n'; // 24
return 0;
}
FFmpeg 選項系統使用偏移量將通用選項表映射到各編解碼器私有結構:
#define OFFSET(x) offsetof(AVCodecContext, x)
static const AVOption options[] = {
{"b", "bitrate", OFFSET(bit_rate), AV_OPT_TYPE_INT64, ...},
{"flags", "flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, ...},
// ...
};
解析器通用邏輯:char* ptr = (char*)ctx + opt->offset; *(int64_t*)ptr = value;,無需知曉 AVCodecContext 完整定義。
static_assert(offsetof(Foo, i) == 4, "Layout changed!"); static_assert(sizeof(Foo) == 24, "Padding changed!");
確保跨平台、跨編譯器版本的二進制介面穩定 (ABI)。
offsetof (C++11 <cstddef>),可攜且安全。