21

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

4

2 回答 2

20

为什么这是 ((type*)0)->member,而不是 (type*)->member

仅仅因为(type*)->member将是无效的语法,因此typeof是不可能的。所以它使用了一个NULL指针,它无论如何都不会取消引用——它只是为了typeof引用成员而使用。


这是如何工作的:

  • typeof技巧用于声明成员类型的指针。这个指针被调用者传递的指针初始化

  • 从指针的地址中减去该成员在结构中的偏移量:这会产生包含对象的地址


更微妙的问题:为什么不摆脱typeof并只做ptr - offsetof. 无论如何,我们都在投射它char *,对吧?在那种情况下,你可以传递任何东西,ptr编译器不会说什么。所以所有typeof东西都用于(基本的)类型检查。

于 2012-12-05T12:42:39.087 回答
7

因为type*是类型而不是结构的有效实例。

指向零的指针用于获取正确的实例,但正如typeof在编译时而不是在运行时解析的那样,指针中使用的地址不必是正确或有效的地址。

于 2012-12-05T12:43:31.273 回答