container_of分析

来源:互联网 发布:社交软件架构 编辑:程序博客网 时间:2024/06/08 18:30
    container_of是linux用的比较多的一个宏定义,他的意义就是通过一个结构体成员变量的地址算出该成员变量所在结构体的地址,这里面有两个宏定义。先看第一个。
#define container_of(ptr, type, member) ({                      \const typeof( ((type *)0)->member ) *__mptr = (ptr);    \(type *)( (char *)__mptr - offsetof(type,member) );})

这个就是container_of的宏定义,第一个变量是成员指针,第二个是结构体类型,第三个是成员类型,不清楚typeof用法的可以去查一查,这是C语言新增的一个关键词,可以用来返回类型,比如int a;可以写成typeof(int) a;  也可以int a;int c;可替换成int a;typeof(a) c;看举的例子应该知道怎么用了吧, 第分析第一句话const typeof( ((type *)0)->member ) *__mptr = (ptr);我们分开解析(type *)0,代表一个type类型的指针,typeof( ((type *)0)->member )这个的含义应该知道吧,也就是代表member成员的类型,所以const typeof( ((type *)0)->member ) *__mptr就是定义了一个member类型的一个指针 __mptr,再将传来的ptr,member的地址赋值给__mptr,所以后续操作就不用ptr了,而用__mptr(其实个人觉得的话没必要在定义一个__mptr变量,也就是可以省略第一行,将第二行的__mptr用ptr代替,可能自己不够严谨,人家内核这么做也有他的理由,哈哈),再看第二行,(type *)( (char *)__mptr - offsetof(type,member) ),也就是用现在成员变量的地址减去该成员变量在结构体中的偏移量,得到的地址就是元素首地址,也就是所在结构体地址,在将其得到的值强制转换乘(type *)结构体类型地址 返回,整个宏定义就完成了,也挺简单的。


下面就分析一下怎么得到他的偏移量,也就是offsetof宏的实现。

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

首先(TYPE *)0,将0强制转换成TYPE类型,也就是结构体类型,也就是这个结构体现在的地址是0,所以他的所有成员都是在0的基础上偏移,所以得到的结构体成员地址就是偏移地址,然后  &(((TYPE *)0)->MEMBER),得到结构体成员的member的地址,再将其强制转换成unsigned int 类型返回。

1 0