#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
最近在看linux kernel中的鏈表操作, 看到了如上這個宏, 其實表達的意思很簡單, 但是他要用一個__mptr來指向ptr甚是不解?實測如下宏也是可行的:
#define container_of(ptr, type, member) ({ \
(type *)( (char *)ptr - offsetof(type,member) );})
內核用一個臨時const變量來存儲ptr是為什麼啊? 並且第一步還要強行獲得ptr的對象類型, 第二步又將mptr強轉成char *類型, 就我目前的知識來看這種操作好雞肋, 內核這樣做是適應編譯器的操作“習慣”嗎? 還是說有其它的“難言之隱“?有大神能幫忙解答一下嗎?
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++)產生副作用
所以, const typeof( ((type *)0)->member ) *__mptr = (ptr);是為了確保不會得到任何ptr表達式,都不會有副作用。