開門見山
offsetof
用于獲取結(jié)構(gòu)體成員的相對偏移,container_of
通過結(jié)構(gòu)體字段獲取結(jié)構(gòu)體地址。
offsetof
offsetof
的標準實現(xiàn)如下,其被定義在stddef.h
中:
#define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)
offsetof
宏的計算發(fā)生在編譯階段。
GCC
編譯器還為此提供一個內(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)?);})
typeof
是GCC
編譯器的一個擴展,用于獲取變量或表達式的類型。在container_of
宏中,typeof( ((type *)0)->member )
用于獲取結(jié)構(gòu)體type
中成員member
的類型。
Linux
內(nèi)核實現(xiàn)中,為了更嚴格的類型檢查,和更好的符合C語言標準,container_of
宏的實現(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_assert
是C11
引入的靜態(tài)斷言機制,__same_type
由GCC
編譯器提供的內(nèi)置函數(shù)實現(xiàn)。
實際應用
container_of
典型的應用就是Linux
內(nèi)核中鏈表的實現(xiàn):
struct?list_head?{
?struct?list_head?*next,?*prev;
};
#define?list_entry(ptr,?type,?member)?
?container_of(ptr,?type,?member)
//?通過鏈表節(jié)點獲取節(jié)點所在結(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)