C 程式設計/stddef.h/函式參考
外觀
C 語言的 offsetof() 宏是 ANSI C 庫中的一項功能,它位於stddef.h中。它計算的是結構體或聯合型別中給定成員相對於結構體或聯合型別開頭的偏移量(以位元組為單位),返回型別為size_t。該offsetof() 宏接受兩個引數,第一個是結構體名稱,第二個是結構體中成員的名稱。它不能被描述為 C 語言的原型。[1]
宏的“傳統”實現依賴於編譯器對指標的處理方式不那麼嚴格;它透過指定一個假設從地址零開始的結構體來獲取成員的偏移量
#define offsetof(st, m) \
((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
它的工作原理是將空指標強制轉換為指向結構體的指標st,獲取結構體中成員m的地址,將該地址強制轉換為字元指標,然後使用指標算術運算減去結構體的基地址,所有這些操作最終得到結構體開頭到成員開頭的字元位置數(即位元組數)。
雖然這在許多編譯器中都能正常工作,但根據 C 標準,它具有未定義的行為,因為它涉及空指標的解引用和違反別名規則的強制型別轉換。如果其中一個引數拼寫錯誤,它也往往會導致令人困惑的編譯器診斷。現代編譯器通常使用特殊形式定義宏,例如[2]
#define offsetof(st, m) __builtin_offsetof(st, m)
在 C 語言中實現通用資料結構時,它非常有用。例如,Linux 核心使用offsetof()來實現container_of(),它允許類似混合型別的東西找到包含它的結構體:[3]
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
該宏用於從指向巢狀元素的指標中檢索包含結構體,例如此處的my_struct物件的連結列表迭代
struct my_struct {
const char * name;
struct list_node list;
};
extern struct list_node * list_next(struct list_node *);
struct list_node * iter = /* ... */
while (iter)
{
struct my_struct * elem = container_of(iter, struct my_struct, list);
printf("%s\n", elem->name);
iter = list_next(&elem->list);
}
- ↑ "offsetof 參考". MSDN. 檢索於 2010-09-19.
- ↑ "GCC offsetof 參考". 自由軟體基金會. 檢索於 2010-09-19.
- ↑ Greg Kroah-Hartman (2003-06). "container_of()". Linux Journal. 檢索於 2010-09-19.
{{cite web}}: 請檢查日期值:|date=(幫助)