前言
本文講解typeof( ((type *)0)->member )
的含義,並在此基礎上學習offset_of()的用法。
typeof( ((type *)0)->member )
ANSI C標準允許值爲0的常量被強制轉換成任何一種類型的指針,並且轉換的結果是個NULL,因此((type *)0)
的結果就是一個類型爲type *
的NULL指針.
如果利用這個NULL指針來訪問type的成員當然是非法的,但typeof( ((type *)0)->member )
是想取該成員的類型(有關typeof()的用法可參考這裏),所有編譯器不會生成訪問type成員的代碼,類似的代碼&( ((type *)0)->member )
在最前面有個取地址符&
,它的意圖是想取member的地址,所以編譯器同樣會優化爲直接取地址。
struct apple{
int weight;
int color;
};
int main(int argc, char *argv[])
{
int weight = 5;
typeof(((struct apple *)0)->weight) *ap1 = &weight;//定義一個指針變量ap1, ap1的類型爲apple成員weight的類型。
printf("ap1's value:%d\n", *ap1);
}
printf("%d\n", offset_of(struct apple, color));
[root@xxx c_base]# ./a.out
ap1's value:5
offset_of()
理解了以上內容後再看offset_of(),它的作用是獲取結構體中某個成員相對於該結構體首元素地址的偏移量。
#define offset_of(type, memb) \
((unsigned long)(&((type *)0)->memb))
比如想知道sruct apple
中的color是在結構體中的哪個位置,可以這麼做:
printf("colore offset addr:%d\n", offset_of(struct apple, color));
[root@xxx c_base]# ./a.out
colore offset addr:4
如上結果表示colore成員在結構體apple中的偏移地址是4.