container_of宏在很久以前的文章我就已经有分析写过了,但是看回去,感觉以前自己对这个宏的表达描述分析能力还是有待提高,毕竟那时候刚接触linux内核不久,整个人都懵懵哒,无法说得让别人通俗易懂。
那么这个宏整体是什么样子的呢?
//获取结构体成员相对于结构体的偏移 #define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)->MEMBER) //通过获取结构体中的某个成员,反推该结构体的指针 #define container_of(ptr, type , member) ({ \ const typeof(((type *)0)->member) *__mptr = (ptr) ; \ (type *)((char *)__mptr - offsetof(type,member)) ;})
作用:通过某个结构体中的某个成员变量的指针,反推这个结构体变量的指针。说白了,我定义一个结构体变量和结构体指针,变量.结构体中某一个成员(这个我是知道的),还有知道它的地址,也就是&(变量.结构体中某一个成员),通过这两个参数,还有结构体的type,返回得到的就是结构体的首地址。
工作原理:
先用typeof获取变量的数据类型,也就是member成员的类型,然后将member这个成员 的指针转成自己类型的指针,再从offsetof相减,就得到整个结构体变量的首地址了,再将该地址强制转化为type *。
关于offsetof的作用就不再阐述,文章超链接在这:Offsetof宏的作用和原理
接下来看看如何使用吧,也很简单。
#include <stdio.h> #include <stdlib.h> //获取结构体成员相对于结构体的偏移 #define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)->MEMBER) //通过获取结构体中的某个成员的,反推该结构体的指针 #define container_of(ptr, type , member) ({ \ const typeof(((type *)0)->member) *__mptr = (ptr) ; \ (type *)((char *)__mptr - offsetof(type,member)) ;}) #pragma pack(4) struct ptr { char a ; short b ; int c ; double d ; }; #pragma pack() int main(void) { struct ptr Pt ; struct ptr *pt ; printf("ptr:%d\n",sizeof(struct ptr));//16 //获取结构体的首地址 printf("ptr:%p\n",&Pt); //0028FEA8 Pt.a = 'a'; Pt.b = 2 ; Pt.c = 4 ; Pt.d = 12.04 ; //通过container_of获取结构体的首地址 pt = container_of(&Pt.c, struct ptr , c); printf("pt:%p\n",pt); //0028FEA8 printf("a:%c\n",pt->a) ; //'a' printf("b:%d\n",pt->b) ; //2 printf("c:%d\n",pt->c) ; //4 printf("d:%.2lf\n",pt->d);//12.04 return 0 ; }
时间: 2024-12-03 19:57:57