linux内核--container_of

最近学习了一下Container_of的使用,给大家分析一下code的实现:

这里写图片描述

container_of的作用是,通过结构体中的成员,来获取结构体的地址,原理上很简单就是:结构成员的地址-其在结构体中的偏移量。
首先我们来看这第一行code,求结构体成员的地址:

const typeof(((type *)0)->member) *__mptr = (ptr));

这其实很简单,就是把 ptr 的地址赋值给 __mptr,类型是
(type *)0->member的类型。这里有个取巧的地方,生成0指针的结构体。
虽然0是一个非法指针,然而此处并没有真正对其进行内存访问(运行期),只是利用其进行计算(编译器),所以不会造成任何程序错误。

typeof(((type *)0)->member);  //取得member的类型
举例:
int y;
typeof(y) x = 200; //等价于 int x = 200; 
                   //这里和 C 中的typeof用法不一样。

第二行code,求结构体首地址:

(type *)((char *)__mptr - offsetof(type,member) );

其中,offsetof(type,member) 是求偏移量的,其定义如下:

#define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)
&((TYPE *)0)->MEMBER) 
//本来得到的是member的地址,但创建的结构体为0//所以该结构的首地址被设置为0地址,这样member的地址就变成了偏移地址。
//由于得到的偏移地址是32位或者64位的值,这时就需要`(size_t)`把它换成整型(int)的偏移量。

最后就是: 结构体的首地址 = 成员地址 - 偏移量。

(type *)((char *)__mptr - offsetof(type,member) );

//为什么__mptr要强制转换为char*呢?
//这是c语言的基础知识,指针的加减对应到地址是根据指针所指的数的类型来确定的。
//如果MEMBER是int,而不把它的指针强制为char*,那么减去的将是4倍的地址偏移,
//当然是不对的。

猜你喜欢

转载自blog.csdn.net/shenjin_s/article/details/79675671