在linux內核驅動中,咱們常常會用到container_of,實際上他是一個宏,其做用是咱們能夠根據該結構體變量中的某個成員首地址從而得到該結構體變量的首地址。linux
其具體的定義以下:spa
#define container_of(ptr, type, member) ({ \ 681 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 682 (type *)( (char *)__mptr - offsetof(type,member) );})
第一個參數ptr: 該結構體變量的一個member的地址;.net
第二參數type:該結構體變量;指針
第三個參數member:該結構體中的一個數據成員;code
當調用container_of()咱們就能夠經過ptr得到該結構體的首地址。blog
一、這裏看到了typeof,它是C語言中的一個關鍵字。能夠用來聲明某個參數的類型。內存
看上面粘貼的那段代碼:get
首先將首地址0強制轉換爲type類型的指針,指向type結構體中的member數據成員,__mptr指針變量的是定義的一個臨時的數據成員類型,該數據類型就是member類型的一個指針,指向ptr。class
二、恰好有offsetof,它也是一個宏,其定義以下:變量
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
這個宏的講解引用高人的理解,連接以下:
http://blog.csdn.net/tigerjb/article/details/8299584
1>( (TYPE *)0 ) 0地址強制 "轉換" 爲 TYPE結構類型的指針;
2>((TYPE *)0)->MEMBER 訪問TYPE結構中的MEMBER數據成員;
3>&( ( (TYPE *)0 )->MEMBER)取出TYPE結構中的數據成員MEMBER的地址;
4>(size_t)(&(((TYPE*)0)->MEMBER))結果轉換爲size_t類型。/*該四部爲粘貼引用*/
宏offsetof的巧妙之處在於將0地址強制轉換爲 TYPE結構類型的指針,TYPE結構之內存空間首地址0做爲起始地址,則成員地址天然爲偏移地址