Linux内核中的container_of()
宏定义为:
#define container_of(ptr, type, member) ({ \
const typeof( ((type*)0)->member) * __mptr =(ptr);\
(type*)( (char*)__mptr - offsetof(type,member) );})
为什么这样用((type*)0)->member
,不行(type*)->member
?
Linux内核中的container_of()
宏定义为:
#define container_of(ptr, type, member) ({ \
const typeof( ((type*)0)->member) * __mptr =(ptr);\
(type*)( (char*)__mptr - offsetof(type,member) );})
为什么这样用((type*)0)->member
,不行(type*)->member
?
为什么这是 ((type*)0)->member,而不是 (type*)->member
仅仅因为(type*)->member
将是无效的语法,因此typeof
是不可能的。所以它使用了一个NULL
指针,它无论如何都不会取消引用——它只是为了typeof
引用成员而使用。
这是如何工作的:
该typeof
技巧用于声明成员类型的指针。这个指针被调用者传递的指针初始化
从指针的地址中减去该成员在结构中的偏移量:这会产生包含对象的地址
更微妙的问题:为什么不摆脱typeof
并只做ptr - offsetof
. 无论如何,我们都在投射它char *
,对吧?在那种情况下,你可以传递任何东西,ptr
编译器不会说什么。所以所有typeof
东西都用于(基本的)类型检查。
因为type*
是类型而不是结构的有效实例。
指向零的指针用于获取正确的实例,但正如typeof
在编译时而不是在运行时解析的那样,指针中使用的地址不必是正确或有效的地址。