关于container_of函数分析
#include <stdio.h> #define offset_of(type,member) ((int)&(((type *)0)->member)) #define container_of(ptr,type,member) ({\ const typeof(((type*)0)->member) *__mptr = ptr;\ (type *)((char *)__mptr - offset_of(type,member));\ }) struct mytest{ char i; int j; char *k; }; int main(){ struct mytest temp; struct mytest *p; printf("&temp = %p\n",&temp); printf("&temp.k = %p\n",&temp.k); printf("&((struct mytest *)0)->k = %d\n",((int)&((struct mytest *)0)->k)); printf("&temp = %p \n",container_of(&temp.j,struct mytest,j)); printf("&temp = %p \n",container_of(&temp.k,struct mytest,k)); return 0;}
(一).分析下宏定义1:
#define offset_of(type,member) ((int)&(((type *)0)->member))
(type * )0 :强制把0地址转化为type *类型
&(((type *)0)->member) :将type类型的member成员的地址取出。这里用法很妙,由于type指针地址是0,故其成员地址都是基地址为0加上偏移地址。
(int)(&(((type *)0)->member)) :将type成员类型地址强制转化为int。
(二).分析下宏定义2:
#define container_of(ptr,type,member) ({\
const typeof(((type*)0)->member) *__mptr = ptr;\
(type *)((char *)__mptr - offset_of(type,member));\
})
2.1. 分析 const typeof(((type *)0)->member) *__mptr = ptr;
const typeof(((type *)0)->member) :typeof是关键字,获取成员类型。此部分是得到宏传过来的成员类型。
const typeof(((type *)0)->member) *__mptr = ptr :此部分为什么要重新定义__mptr呢?这就是写linux内核工程师的牛逼,严谨之处。如果开发者使 用时输入的参数有问题:ptr与member类型不匹配,编译时便会有warnning, 但是如果去掉改行,那个就没有了,而这个警告恰恰是必须的(防止出错有不 知道错误在哪里)。。。
2.2. 分析(type *)((char *)__mptr - offset_of(type,member));
(char *)__mptr :将成员类型强制转化为char *,如此地址进行加减时以字节为单位
(char *)__mptr - offset_of(type,member) :计算出结构体首地址,此时地址类型为char *
(type *)((char *)__mptr - offset_of(type,member)):将char * 强制转化为(type *)
索引文献:https://blog.csdn.net/s2603898260/article/details/79371024