一个更易读的版本:
#define container_of(ptr, type, member) ( \
{ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) ); \
} \
)
简而言之,该宏定义了一个可用于if和其他语句中的“test”。((type *) 0)将空引用转换为相关类型,然后获取该类型的'member'子组件。typeof()宏将返回与成员子“对象”关联的类型。因此,它创建了一个常量__mptr变量,其类型与type.member子组件相同。例如,如果我们有:
typedef struct foo_s {
int bogus;
int bar;
} foo;
如果按照以下方式调用:
foo blah; /* and initialize it of course */
int *myptr = &foo.bar;
foo *result = container_of(myptr, foo, bar);
然后宏的第一行将变成以下内容:
const int *__mptr = (myptr);
宏的第二行计算原始结构体的内存位置,并返回该结构体的内存指针,并适当地将其转换为该结构体,展开后如下所示:
(foo *)( (char *)__mptr - offsetof(foo, bar));
结果如下所示:
foo *result = container_of(myptr, foo, bar);
允许您获取结构体中的myptr元素,并从其中提取指向原始容器的指针。
现在,在上面的示例中,这并不实用,因为您已经可以访问包含的结构体。但是假设您没有访问权限,因为您正在使用的 API 没有传递它。这个宏是一个巧妙的方法,可以在通常不可用时获取父容器。
当然,更好的做法是构建一个更好的 API,不需要此 hack。但是如果必要,它非常有用。
({ })
用于在表达式中评估具有局部变量的块,以及typeof
用于声明与成员类型相同的变量。 - Jens Gustedt