#include <stdio.h>
#define STRUCT_OFFSET(stru_name, element) (unsigned long)&((struct stru_name*)0)->element
struct stru_addr
{
int a;
char b;
int d;
char c;
};
int main(void)
{
struct stru_addr s;
printf("start addr of s = %x\n", &s.a);
unsigned long offset = STRUCT_OFFSET(stru_addr, c);// 這個就是成員c的相對於首地址的相對地址了
printf("c_addr = %x, offset = %u\n", &s.c, offset);
printf("start addr of s caculated from c addr: %x\n", (char *)&s.c - offset);//這個就是首地址了
return 0;
}
其實整個程序中最關鍵的部分就是如何求出結構體中某個成員相對於結構體首地址的偏移量。這裏的解決方法是:假設存在一個虛擬地址0,將該地址強制轉 換成爲該結構體指針類型(struct stru_name*)0。那麼地址0開始到sizeof(struct)-1長度的內存區域就可以視爲一個結構體的內存。這樣結構體中任何一個元素都可 以通過對該結構體指針解引用得到。由於該結構體的起始地址爲0, 因此任何一個成員的地址應該等於其相對於結構體起始地址的偏移,這也就是計算偏移量的方法:(unsigned long)&((struct stru_name*)0)->element。
上面程序執行的結果如下:
start addr of s = bfad7ac0
c_addr = bfad7acc, offset = 12
start addr of s caculated from c addr: bfad7ac0
上述的結果中還同時考慮了結構體內的對齊問題。