宏的作用
该宏的作用就是根据结构体中一个成员变量的地址求结构体首地址
如何做到
如果要想根据结构体成员的地址求结构体的首地址,我们需要分三步:
第一步:明确成员变量的地址;
第二步:计算成员变量在该结构体中的偏移;
第三步:用第一步求出的成员变量地址减去偏移值,既得出结构体的首地址
container_of宏如何做的
首先我们先看下该宏的原型:
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
根据上面我们列出的三步,我们分开来看:
第一步:明确成员变量地址
const typeof( ((type *)0)->member ) *__mptr = (ptr);
此处将成员变量地址ptr,赋值给临时变量__mptr
typeof是标准C库中的函数,函数返回参数的数据类型,此处即返回成员变量member的类型,并根据member的类型定义临时指针变量__mptr
第二步:计算成员变量在结构体中的偏移
offsetof(type,member)
offsetof为标准C库中的函数,函数作用就是求出member成员在结构体中的偏移。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
这个宏的运行机理如下:
一共4步
1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址;
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型。巧妙之处在于将0转换成(TYPE*),结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址;
第三步:结构体成员变量地址减去成员变量的偏移
(type *)( (char *)__mptr - offsetof(type,member) );
取成员变量的地址__mptr减去该成员变量在结构体中的偏移,即可得到type类型结构体的首地址