linux内核container_of宏解析

在看linux内核的源代码的时候,经常会看到一个宏,就是container_of,它的作用是由一个结构体的成员指针得到这个结构体的指针。看的多了,就想搞明白这是怎么个东西,打开source insight一看,这个宏定义在include/linux/kernel.h这个头文件里边,打开一看,定义如下
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:	the pointer to the member.
 * @type:	the type of the container struct this is embedded in.
 * @member:	the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})


这个宏有三个参数,ptr是结构体成员的指针,type是这个结构体的类型,member是成员的变量名。
就这三行的代码,让我想了半天,最后还去网上查了查,最后才搞明白了,不得不承认C语言真的是博大精深,而linux内核的源代码真的是C语言的圣堂,这么优秀(可以用惊天地泣鬼神来形容了)的代码,也就在这里能看到了。
首先看第一行,const typeof( ((type *)0)->member ) *__mptr = (ptr);
这一行就是把0强转为一个type类型的指针,这个类型的成员member来定义一个指针__mptr,__mptr的值就是传入的ptr的值。
再来看第二行,(type *)( (char *)__mptr - offsetof(type,member) );
这一行把上一行得到的__mptr的地址减去member在type里的偏移值,就是type的结构体的指针。
这个offsetof又是什么鬼!
经过查找,offset定义在linux/compiler.h头文件里,定义如下
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif /* __KERNEL__ */


如果定义了__compiler_offsetof宏,就是用编译器内建的__compiler_offsetof,如果编译器没有定义这个宏,就使用#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)这个宏。
这个宏把0强行转化为TYPE类型的指针,然后指向他的member成员,由于这个指针的基地址是0,所以他的member成员的地址就是在0的基础上加上member的前边的变量的字节数,就是member在type结构体里边的偏移。
真的很完美的解决,至少我是佩服的一塌糊涂。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值