• 正文
    • 開(kāi)門見(jiàn)山
    • 實(shí)際應(yīng)用
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

【LeafC】C語(yǔ)言之宏魔法4:offsetof&container_of

02/10 22:50
631
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

開(kāi)門見(jiàn)山

offsetof用于獲取結(jié)構(gòu)體成員的相對(duì)偏移,container_of通過(guò)結(jié)構(gòu)體字段獲取結(jié)構(gòu)體地址。

offsetof

offsetof的標(biāo)準(zhǔn)實(shí)現(xiàn)如下,其被定義在stddef.h中:

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

offsetof宏的計(jì)算發(fā)生在編譯階段。

GCC編譯器還為此提供一個(gè)內(nèi)置函數(shù)__builtin_offsetof以提高編譯效率:

#define?offsetof(TYPE,?MEMBER)?__builtin_offsetof(TYPE,?MEMBER)

container_of

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

typeofGCC編譯器的一個(gè)擴(kuò)展,用于獲取變量或表達(dá)式的類型。在container_of宏中,typeof( ((type *)0)->member )用于獲取結(jié)構(gòu)體type中成員member的類型。

Linux內(nèi)核實(shí)現(xiàn)中,為了更嚴(yán)格的類型檢查,和更好的符合C語(yǔ)言標(biāo)準(zhǔn),container_of宏的實(shí)現(xiàn)如下:

#define?container_of(ptr,?type,?member)?({????
?void?*__mptr?=?(void?*)(ptr);?????
?static_assert(__same_type(*(ptr),?((type?*)0)->member)?||?
????????__same_type(*(ptr),?void),???
????????"pointer?type?mismatch?in?container_of()");?
?((type?*)(__mptr?-?offsetof(type,?member)));?})

static_assertC11引入的靜態(tài)斷言機(jī)制,__same_typeGCC編譯器提供的內(nèi)置函數(shù)實(shí)現(xiàn)。

實(shí)際應(yīng)用

container_of典型的應(yīng)用就是Linux內(nèi)核中鏈表的實(shí)現(xiàn):

struct?list_head?{
?struct?list_head?*next,?*prev;
};
#define?list_entry(ptr,?type,?member)?
?container_of(ptr,?type,?member)

//?通過(guò)鏈表節(jié)點(diǎn)獲取節(jié)點(diǎn)所在結(jié)構(gòu),以下為示意,省略部分代碼
struct?my_struct?{
????int?a;
????char?b;
????struct?list_head?node;
};
struct?my_struct?data;
struct?my_struct?*entry?=?list_entry(&data,?struct?my_struct,?node)

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄