Linux的c语言哲学之offsetof和container_of

Linux的c语言哲学之offsetof和container_of

内核版本作者
Linux4.4nineyole

offsetof

针对宏定义的详细说明

宏定义源码如下:

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

offsetof宏定义的主要作用:获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。

( (TYPE *)0 )

上面代码是将0强制转换为一个类型为TYPE类型的指针,并且这个TYPE类型的指针的地址是0。

((TYPE *)0)->MEMBER

上面代码是访问结构TYPE中的的MEMBER数据成员。

&( ( (TYPE *)0 )->MEMBER )  

上面代码是取出数据成员MEMBER的地址。并且由于TYPE的地址是0,因此获取到的地址就是相对成员MEMBER在结构体TYPE中的偏移。

(size_t)(&(((TYPE*)0)->MEMBER))  

将得到偏移结果转换类型。对于32位系统而言,size_t是unsigned int类型;对于64位系统而言,size_t是unsigned long类型。

图解offsetof

img

相当于有一个结构体TYPE,求这个结构体中其中一个成员变量MEMBER在该结构体的中偏移位置。

注意事项:需要考虑在编译过程中的结构体对齐问题。

container_of

#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

针对宏定义的详细说明

主要作用:根据结构体(type)变量中的域成员变量(member)的指针(ptr)来获取指向整个结构体变量的指针。

代码解释:

第一行

typeof( ( (type *)0)->member ) 

表示取出结构体type变量的member成员的变量类型。

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

表示利用member的类型定义一个 __mptr指针,并且这个指针指向成员变量member所指向的地址。

第二行

(char *)__mptr

将__mptr指针强制类型转换成字节型指针。

offsetof(type,member))    

这个前面讲过了,就是获取member成员在结构体type中的位置偏移。

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

就是用成员变量的绝对地址减去member在结构体type中的偏移位置,就表示结构体type的指针的起始地址,这个时候还是为char *型指针。

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

就是将char *指针类型的结构体type的指针(表示type的绝对地址)强制转换成type *类型的结构体type的指针。

图解container_of

img

相当于已知一个结构体type的成员member的地址,去获取这个结构体的地址。其实现原理就是通过offsetof获取member在type中的偏移地址,然后经过一系列类型转换获得的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nineyole

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值