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
?
答案 0 :(得分:19)
为什么这是((type *)0) - > member,not(type *) - > member
仅仅因为(type*)->member
语法无效,因此typeof
是不可能的。所以它使用了一个NULL
指针,它无论如何都不会取消引用 - 它只是用typeof
可以引用该成员。
这是如何运作的:
typeof
技巧用于声明成员类型的指针。使用调用者传递的指针
从结构的地址中减去结构中该成员的偏移量:这会产生包含对象的地址
Subtler问题:为什么不摆脱typeof
,只做ptr - offsetof
。我们无论如何都要把它投到char *
,对吧?在这种情况下,您可以传递任何内容ptr
,编译器不会说任何东西。所以整个typeof
事物都是(基本的)类型检查。
答案 1 :(得分:7)
因为type*
是一种类型而不是结构的有效实例。
指向零的指针用于获取正确的实例,但由于typeof
在编译时解析而不是在运行时,指针中使用的地址不必是正确的或有效的地址。