linux中container_of

linux中container_of(ptr, type, member)宏的作用是傳入結構體類型type的域member地址ptr,返回該結構體變量的首地址,定義如下:

#define container_of(ptr, type, member) ({   \
          const typeof( ((type *)0)->member ) *__mptr = (ptr); \
          (type *)( (char *)__mptr - offsetof(type,member) );})

 

這個宏裏面有2處事GNU C獨有的特性:

1:typeof(x)的意思是取x的類型,GNU C支持而ANSI C不支持

2:GNU C把包含在括號裏的複合語句看做是一個表達式,稱爲語句表達式,它可以出現在任何允許表達式的地方。我們可以在語句表達式中使用原本只能在複合語句中使用的循環變量、局部變量等

例如int aa = ({3; 43-5;});使用不支持GNU C的編譯器會報錯,而使用gcc會得到aa爲38
利用GNU C的這種特性,我們可以避免一些宏定義產生副作用,如使用

#define min_t(type,x,y) \
                ({type __x=(x); type __y=(y);__x<__y?__x:__y})
代替

#define min(x,y) ((x)<(y)?(x):(y))
可避免傳入min(a++,b++)產生副作用

 

下面具體分析這個container_of的實現:

1:const typeof( ((type *)0)->member ) *__mptr = (ptr);定義一個和member相同類型的變量__mptr,並把member地址賦給它

 

2:#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
宏的作用是傳入結構體類型TYPE和其中的域MEMBER,返回該域在結構體中的偏移地址

 

3:(type *)( (char *)__mptr - offsetof(type,member) );得到結構體的首地址,並強制轉換成type*類型

 

 

測試程序如下:
#include <stdio.h>

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

#define container_of(ptr, type, member) ({   \
          const typeof( ((type *)0)->member ) *__mptr = (ptr); \
          (type *)( (char *)__mptr - offsetof(type,member) );})

typedef struct CONTAIN_s
{
 char a;
 int b;
 char c[10];
}CONTAIN_t;

int main(void)
{
 CONTAIN_t *pcon;
 CONTAIN_t con = {'3', 4, "abc"};
 pcon = container_of(&con.b, CONTAIN_t, b);

 printf("addr &con %p, addr pcon %p\n", &con, pcon);

 return 0;
}


輸出:addr &con 0xbfd4bad8, addr pcon 0xbfd4bad8


typeof關鍵字的用法

http://www.cublog.cn/u3/101356/showart_2081601.html


轉自:http://rookieubuntu.blog.sohu.com/179419212.html


發佈了73 篇原創文章 · 獲贊 13 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章