__builtin_offsetof(a,b)的用法

-------------linuxcompiler-gcc4.h--------------
#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
分析準備:__compiler_offsetof(),爲gcc編譯器中的編譯方面的參數,查閱gcc方面的文檔:
--->gcc.pdf.Download from www.gnu.org 。其中解釋如下:
#define offsetof(type, member) __builtin_offsetof (type, member)

自己分析:即:__builtin_offsetof(a,b)就是#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)。__builtin_offsetof(a,b)和offsetof(TYPE,MEMBER)本質一樣的,只是 offsetof()宏是由程序員自己來設計(詳見後面講解)。而__builtin_offsetof()宏就是在編譯器中已經設計好了的函數,直接調 用即可。明白了這個區別後,下面的代碼很好理解。

-------linuxstddef.h-----offsetof()-----------
#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
-------------------------------
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
1.對__compiler_offsetof()宏的分析:
__compiler_offsetof來確認編譯器中是否內建了功能同offsetof()宏一樣的宏。若已經內建了這樣的宏,則 offsetof()就是使用這個內建宏__compiler_offsetof()即:__builtin_offsetof()宏。如果沒有定義 __compiler_offsetof()宏,則offsetof()宏就由程序員來設計之。

2.對offsetof()宏的分析:(以下引用論壇)---曾經的騰訊QQ的筆試題。
宿舍舍友參加qq筆試,回來討論一道選擇題,求結構中成員偏移。
想起Linux內核鏈表,數據節點攜帶鏈表節點,通過鏈表訪問數據的方法,用到offsetof宏,今天把它翻了出來:
#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER )

一共4步
1. ( (TYPE *)0 ) 將零轉型爲TYPE類型指針;
2. ((TYPE *)0)->MEMBER 訪問結構中的數據成員;
3. &( ( (TYPE *)0 )->MEMBER )取出數據成員的地址;
4.(size_t)(&(((TYPE*)0)->MEMBER))結果轉換類型.巧妙之處在於將0轉換成(TYPE*),結構以內存空間首地址0作爲起始地址,則成員地址自然爲偏移地址;
舉例說明:
#include<stdio.h>
typedef struct _test
{
char i;
int j;
char k;
}Test;
int main()
{
Test *p = 0;
printf("%p ", &(p->k));
}
自己分析:這裏使用的是一個利用編譯器技術的小技巧,即先求得結構成員變量在結構體中的相對於結構體的首地址的偏移地址,然後根據結構體的首地址 爲0,從而得出該偏移地址就是該結構體變量在該結構體中的偏移,即:該結構體成員變量距離結構體首的距離。在offsetof()中,這個member成 員的地址實際上就是type數據結構中member成員相對於結構變量的偏移量。對於給定一個結構,offsetof(type,member)是一個常 量,list_entry()正是利用這個不變的偏移量來求得鏈表數據項的變量地址。

 

From: http://www.unixresources.net/linux/clf/linuxK/archive/00/00/58/71/587168.html

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