--- tags: data structure, linux kernel, offsetof --- # Linux Kernel 中的 offset 巨集 ## 說明 ```c #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER) ``` `offsetof` 巨集被定義在 `include/linux/stddef.h` 中。它的主要功能是用來計算某一個結構的成員距離該結構之起始位址的偏移量 (offset) 。其中 `TYPE` 為結構的名稱,`MEMBER` 為結構成員的名稱。 `(TYPE *)0` 將數值 `0` 強制轉型為 `TYPE *` 型別。 `0` 則被視為結構 (TYPE) 的起始位址。而 `&((TYPE *)0)->MEMBER` 就可以得到 `MEMBER` 的位址。因為起始位址已被設定為 `0` ,所以 `MEMBER` 的位址就是結構起始點到 `MEMBER` 的偏移量。 ## 範例 寫個範例研究一下 `offsetof` 巨集的行為。 ```c #include <stdio.h> #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define my_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)1000)->MEMBER) struct test { int a; int b; int c; }; int main() { printf("sizeof(int): %ld\n", sizeof(int)); printf("--- offsetof -------------\n"); printf("-------- a: %ld\n", offsetof(struct test, a)); printf("-------- b: %ld\n", offsetof(struct test, b)); printf("-------- c: %ld\n", offsetof(struct test, c)); printf("--- my_offsetof -------------\n"); printf("-------- a: %ld\n", my_offsetof(struct test, a)); printf("-------- b: %ld\n", my_offsetof(struct test, b)); printf("-------- c: %ld\n", my_offsetof(struct test, c)); return 0; } ``` 在範例程式中定義了 `offsetof` 與 `my_offsetof` 兩個巨集,並分別將起始位址設定為 `0` 與 `1000` 將程式編譯並執行後,可得下面的結果。 ``` $ gcc test.c -o test $ ./test sizeof(int): 4 --- offsetof ------------- -------- a: 0 -------- b: 4 -------- c: 8 --- my_offsetof ------------- -------- a: 1000 -------- b: 1004 -------- c: 1008 ``` ## 結論 因此,我們可以得知 ==`&((TYPE *)0)->MEMBER` 的功能就是在計算由結構起始位置到 `MEMBER` 間的偏移量。==