赞
踩
#define container_of(ptr, type, member) ({ /
const typeof( ((type *)0)->member ) *__mptr = (ptr); /
(type *)( (char *)__mptr - offsetof(type,member) );})
分析:
其中:
typeof:这是gcc的C语言扩展保留字, 用于从变量获取类型
ptr:指向结构体中元素member的指针
((type *)0):将整数型0强制转换成结构体类型的指针;表示地址0
((type *)0)->member:该指针指向结构体元素member;
typeof( ((type *)0)->member ):获得结构体元素的类型
__mptr:__mptr是member类型的指向member地址的常量指针。
所以,这一部分的作用就是:创建一个合适类型的常量指针指向结构体。
分析:
offsetof(type,member) :这个宏定义在就是获得结构体元素member的偏移量(字节为单位)
(char *)__mptr :将指向member的指针强制转换成char *类型,以便后面计算。
所以总的来说,这一部分的作用就是利用member的地址减去member的偏移量来计算结构体的地址,然后将结构体的地址转换成type *类型。
其实它的语法很简单,只是一些指针的灵活应用,它分两步:
第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。
第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。
/* time:2020年8月31日14:55:17 objective:理解container_of宏 function:知道结构体中某变量的指针(地址)和偏移量offsetof(type,member)(&((type*)0)->member) 反求结构体首地址 author:wu_junwu */ #include<stdio.h> //获得结构体中某变量member的偏移量 #define offsetof(type,member)((int)&((type*)0) -> member) /* _mptr 是变量member的指针,强制转换类型为const typeof(((type*)0)->member) 结构体的首地址,用(type*)强制转换 type(m)的作用是由变量m可以得知变量m的数据类型 */ #define container_of(ptr,type,member)( { \ const typeof(((type*)0)->member) *_mptr=(ptr);(type*)((char*)_mptr - offsetof(type,member));}) //定义结构体 struct definestruct { int a; char b; short c; long d; }; //主函数 int main(void) { struct definestruct ds; //重命名结构体 struct definestruct init_struct={1,'t',2,15}; //初始化结构体 struct definestruct *ps=NULL; //初始化指针ps,该指针用于指向结构体首地址 short *p=&(ds.c); //定义指针p并初始化,该指针指向的是container_of宏中的已知的地址 ps=container_of(p,struct definestruct,c); //结构体地址ps printf("结构体的首地址=%p\n",ps); printf("&a=%p\n",&(ps->a)); printf("&b=%p\n",&(ps->b)); printf("&c=%p\n",&(ps->c)); printf("&d=%p\n",&(ps->d)); printf("a=%d\n",ps->a); printf("a=%d\n",ds.a); //不能写成 printf("a=%d\n",ds->a); printf("a=%d\n",init_struct.a); printf("b=%d\n",init_struct.b); printf("c=%d\n",init_struct.c); printf("d=%d\n",init_struct.d); return 0; } /* conclusion: 第一步:定义#define offsetof(type,member)(&((tye*)0)->member) 第二步:定义#define container(ptr,type,member)({ const typeof(((type*)0)->member) *_mptr=(ptr);\ // 变量member的指针为常量(const) (type*)((char*)_mptr - offsetof(type,member));}) //强制转换类型type* 第三步:输出结构体首地址。 container宏的作用是求出结构体指针,然后结构体指针可以访问结构体中所有的变量member( 变量的地址或变量本身的值) 疑问;为什么每一次运行的printf("结构体的首地址=%p\n",ps);结果都不一样???? */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。