container_of 和 offsetof 解析

offsetof

原型:

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

作用:

得到MEMBER在TYPE类型的结构体中的偏移量。

解析:

((TYPE )0)->MEMBER :
在c语言中,地址也是用整数来表示的,这里的0,指的是地址,也可以理解为一个指向0地址的指针;(TYPE*)0就是把该地址转换成TYPE类型的的地址,也可以理解成指针转换,现有一个TYPE
的指针,指向的地址为0;那么这个语法连起来就是:找到了TYPE类型的结构体中MEMBER这个成员。

&((TYPE *)0)->MEMBER:
相较于上面,加了一个取地址运算符,这个得到了指向MEMBER这个成员的地址,因为MEMBER所在的struct起始地址是0,所以MEMBER的这个地址,其实就是MEMBER在结构体中的偏移量

container_of

原型:

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

在这里插入图片描述
参数:

  • ptr, 指向的是结构体中的一个成员
  • type, struct object
  • member, ptr指向的那个成员的名字,图中就是list

返回值:

return: 返回的是ptr指向的成员所在结构体的地址。

作用:

现有一个结构体obj,定义如上图所示。但是不知道obj的地址,知道的是obj里面的一个成员list的地址,记为ptr;container_of能够根据此信息获得obj的地址。

解析:

typeof( ((type *)0)->member ) :
(type *)0)->member得到了member这个成员,再用typeof取出它的类型。
const typeof( ((type *)0)->member ) *__mptr = (ptr); 这个是把ptr转换成了这个结构体类型的指针。

(type *)( (char )__mptr - offsetof(type,member) ):
我知道member的地址__mptr, 也能得到member在结构体中的偏移,那么相减就得到了结构体的地址。注意需要转换成char
来进行指针的减。

代码

#include <stdio.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})
struct s{
    char m1;
    char m2;
    char m3;
    s(char _1, char _2, char _3):m1(_1),m2(_2),m3(_3){}
};
int main()
{
    struct s *ss = new struct s('a','b','c');
    char* _m2 = (char*)(&ss->m2);
    struct s *temp = container_of(_m2, struct s, m2);
    printf("ss: %p, _m2:%p, temp:%p\n", ss, _m2, temp);//temp和ss指向的是同一个地址
    typeof(((struct s *)0)->m2) c;
    printf("%ld\n", (size_t) &((struct s*)0)->m2);//m2的偏移量
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值