如何使用宏求結構體的內存偏移地址

#define OffSet(type,field) ((size_t)&(((type*)0)->field))

在C語言中,ANSI C標準允許值爲0的常量被強制轉換成任何一種類型的指針,而且轉換結果是一個空指針,即NULL指針,因此對0取指針的操作((type*)0)的結果就是一個類型爲type*的NULL指針。 但是如果利用這個NULL指針來訪問type類型的成員當然是非法的。

因爲&(((type*)0)->field)的意圖只不過是計算field字段的地址,C語言編譯器根本不生成訪問type成員的代碼,而僅僅是根據type的內容佈局和結構體實例地址在編譯期計算這個常量地址,這樣就完全避免了通過NULL指針訪問內存可能出現的問題。同時又因爲結構體地址是0,所以字段地址的值就是字段相對於結構體基址的偏移。

程序示例如下:

#include <stdio.h>
#define OffSet(type,field) ((size_t)&(((type*)0)->field))
struct Mystr{
	char a;
	short b;
	double c;
	int d;
};
int main()
{
	printf("%d\n",OffSet(struct Mystr,a));
	printf("%d\n",OffSet(struct Mystr,b));
	printf("%d\n",OffSet(struct Mystr,c));
	printf("%d\n",OffSet(struct Mystr,d));
	return 0;
}
程序運行結果爲(32位機器,char佔一個字節,short佔兩個字節,double佔8個字節,int佔4個字節):

0

2

8

16

結果分析:

上述方法避免了實例化一個type對象,而且求值是在編譯期間進行,沒有運行期負擔,程序效率大大提高。

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