程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> 編譯器-關於linux kernel中的container_of宏的困惑

編譯器-關於linux kernel中的container_of宏的困惑

編輯:編程綜合問答
關於linux kernel中的container_of宏的困惑

#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表達式,都不會有副作用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved