首先看看函数的原型:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
其原理是利用,结构体中的一个成员变量的地址获得该结构体的首地址。
其中:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
注: typeof 关键字是用来定义变量数据类型的。
如: 把y定义成x指向的数据类型: typeof(*x) y;
解析如下:
const typeof ( ( (type * )0) -> member) * __mptr =(ptr); //定义 一个(type *)0->member 类型的指针变量 __mptr 并且将ptr赋给__mptr;也就是临时存放ptr的地址(这里的还有一个作用,可以检查ptr的类型是否与member相同)。
(type *)( (char *)__mptr - offsetof(type, member) );//该结构体成员变量的地址减去该结构体成员变量地址的偏移量,就可以得到该类型结构体的首地址。
offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) // 求取该结构体的成员member的从该结构体起始位置的大小。
这里(type *)0 ->member: (type*)0 是将变量0强行转化成type类型结构体的指针,也就是作为该结构体起始地址的指针。
&((TYPE *)0)->MEMBER的作用是求MEMBER到起始指针的地址大小,也就是成员MEMBER相对于(type *)0 的相对偏移量,并通过(size_t)强行将偏移量转化成size_t类型。
所以&((TYPE *)0)->MEMBER)就是求member成员变量相对于(type *)0的大小。
在实际中用法:
来源:CSDN
作者:stoic163
链接:https://blog.csdn.net/stoic163/article/details/103459914