offsetof

16.offsetof宏
#define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)-> MEMBER)
上式是offsetof的定義式,其中TYPE是結構體變量類型,MEMBER是結構體中的成員,返回的是該成員的地址相對結構體首地址的偏移量。
offsetof宏的原理:我們虛擬一個type類型結構體變量,然後用type.member的方式來訪問哪個member元素,繼而得到member相對整個變量首地址的偏移量。
解析((int) &((TYPE *)0)-> MEMBER):
(TYPE *)0:將地址0強制類型轉化爲指向TYPE類型的指針,可以記爲p = (TYPE *)0;p是指向TYPE類型的指針,它的值爲0;
((TYPE *)0)-> MEMBER:->的優先級高一些,將該指針指向結構體中的MEMBER成員;
&((TYPE *)0)-> MEMBER):對該成員取地址;該值即爲MEMBER成員的偏移量,因爲該結構體類型的首地址爲0.
((int) &((TYPE *)0)-> MEMBER):將該地址轉換成int,
offsetof中的亮點就是將該結構體的首地址強制爲0.
struct mystruct
{
char a;
int b;
short c;
};


#define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)-> MEMBER)


int main(void)
{
int offseta = (int)offsetof(struct mystruct, a);
printf("offseta = %d.\n", offseta);
int offsetb = (int)offsetof(struct mystruct, b);
printf("offseta = %d.\n", offsetb);
int offsetc = (int)offsetof(struct mystruct, c);
printf("offsetc = %d.\n", offsetc);
}


/****************************************************************/


當然,在我們定義簡單的結構體變量的時候,我們是可以直接通過轉換來計算偏移量的,方法如下:
struct mystruct
{
char a; // 0
int b; // 4
short c; // 8
};
int main(void)
{
printf("整個結構體變量的首地址:%p.\n", &s1); //&s1取結構體首地址
printf("s1.b的首地址:%p.\n", &(s1.b)); //&(s1.b)取b成員地址
printf("偏移量是:%d.\n", (char *)&(s1.b) - (char *)&s1); //b對整個結構體的偏移量
}


/****************************************************************/
我們也可以先讓一個指針指向該結構體的首地址,然後將該指針移動適當的偏移量,然後解引用移動後的指針來獲取對應成員的值。
struct mystruct
{
char a; // 0
int b; // 4
short c; // 8
};


int main(void)
{
struct mystruct s1;
s1.b = 12;

int *p = (int *)((char *)&s1 + 4); //&s1,結構體的首地址,(char *)&s1轉爲字符形式指針,然後指針走4個偏移
printf("*p = %d.\n", *p);


}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章