1.offset宏講解
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
對這個宏的講解我們大致可以分為以下4步進行講解:
1>( (TYPE *)0 ) 0地址強制 "轉換" 為 TYPE結構類型的指針;
2>((TYPE *)0)->MEMBER 訪問TYPE結構中的MEMBER數據成員;
3>&( ( (TYPE *)0 )->MEMBER)取出TYPE結構中的數據成員MEMBER的地址;
4>(size_t)(&(((TYPE*)0)->MEMBER))結果轉換為size_t類型。
宏offsetof的巧妙之處在於將0地址強制轉換為 TYPE結構類型的指針,TYPE結構以內存空間首地址0作為起始地址,則成員地址自然為偏移地址。可能有的讀者會想是不是非要用0呢?當然不是,我們僅僅是為了計算的簡便。也可以使用是他的值,只是算出來的結果還要再減去該數值才是偏移地址。來看看如下的代碼:
#include<stdio.h>
#defineoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)4)->MEMBER)
struct test_struct {
int num;
char ch;
float f1;
};
int main(void)
{
printf("offsetof (struct test_struct,num)=%d\n",offsetof(struct test_struct,num)-4);
printf("offsetof (structtest_struct,ch) =%d\n",offsetof(struct test_struct,ch)-4);
printf("offsetof (struct test_struct,f1)=%d\n",offsetof(struct test_struct,f1)-4);
return 0;
}
運行結果為:
jibo@jibo-VirtualBox:~/cv_work/work/list/offset $ ./main
offsetof (struct test_struct,num) =0
offsetof (struct test_struct,ch) =4
offsetof (struct test_struct,f1) =8
為了讓大家加深印象,我們在代碼中沒有使用0,而是使用的4,所以在最終計算出的結果部分減去了一個4才是偏移地址,當然實際使用中我們都是用的是0。
二.舉例體會offsetof宏的使用:
#include<stdio.h>
#defineoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
struct test_struct {
int num;
char ch;
float f1;
};
int main(void)
{
printf("offsetof(struct test_struct,num) =%d\n",offsetof(struct test_struct,num));
printf("offsetof (structtest_struct,ch) =%d\n",offsetof(struct test_struct,ch));
printf("offsetof (struct test_struct,f1)=%d\n",offsetof(struct test_struct,f1));
return 0;
}
執行結果為:
jibo@jibo-VirtualBox:~/cv_work/work/list/offset $ ./main
offsetof (struct test_struct,num) =0
offsetof (struct test_struct,ch) =4
offsetof (struct test_struct,f1) =8