container_of() 宏函數(shù)源碼:
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
函數(shù)作用:
??????????????????????????????? 根據(jù)某結(jié)構(gòu)體任意一個(gè)成員首地址,獲得整個(gè)結(jié)構(gòu)體變量的首地址。
原理:
??????????????????????????????? 某結(jié)構(gòu)體的任意一個(gè)成員的相對(duì)地址 減去 該成員在該結(jié)構(gòu)體中的絕對(duì)偏移 就是該結(jié)構(gòu)體的相對(duì)首地址
實(shí)例:
??????????????????????????????? struct TEST
????????????????????????????????? {
???????????????????????????????????????????? int a;
???????????????????????????????????????????? char b;
???????????????????????????????????????????? float c;
??????????????????????????????????? };
該結(jié)構(gòu)體的內(nèi)存分配如下圖:
?

struct TEST mTEST={10,'F',12.12};
char *pB=&mTEST.b;
假如pB地址等于0xAABBCC04,根據(jù)內(nèi)存分配推斷mTEST的首地址應(yīng)該為:0xAABBCC00
那么container_of()如何根據(jù)pB變量獲得mTEST的首地址呢?
步驟如下:
1.利用GNU C標(biāo)準(zhǔn)中的 typeof 關(guān)鍵字,根據(jù)結(jié)構(gòu)體struct TEST的成員b,定義一個(gè)和b同類型的臨時(shí)變量指針用來(lái)存儲(chǔ)輸入ptr.
const typeof( ((struct TEST *)0)->b ) *__mptr = (ptr);
2.利用offsetof()獲得成員變量b在結(jié)構(gòu)體struct TEST中的絕對(duì)偏移量=4,而__mptr=0xAABBCC04,所以獲得mTEST的首地址=0xAABBCC00
? 和推斷一樣。為什么用(char *)強(qiáng)制類型轉(zhuǎn)換__mptr,是為了讓指針__mptr按一個(gè)字節(jié)一個(gè)字節(jié)偏移,要不然會(huì)根據(jù)__mptr數(shù)據(jù)類型進(jìn)行偏
?? 移,算出來(lái)的地址就不對(duì)了。
(struct TEST *)( (char *)__mptr - offsetof(struct TEST,b) );