Linux中的offsetof/container_of宏

本文详细解析了offsetof宏用于计算结构体成员偏移量的方法,以及container_of宏如何根据成员变量获取结构体首地址。通过实例展示了这两个宏在实际编程中的应用,帮助理解结构体内存布局的关键概念。
摘要由CSDN通过智能技术生成

offsetof宏

/*计算结构体成员在结构体中的偏移量*/
#define  offsetof(TYPE, MEMBER)            ((size_t) &((TYPE *)0) -> MEMBER)

offsetof宏作用
用于计算结构体成员在结构体中的偏移量

offsetof宏原理
TYPE : 结构体的类型

MEMBER : 结构体成员

使用结构体类型定义一个指针并指向结构体成员,表示该地址从0开始到结构体成员地址的偏移,即可计算出偏移量。

container_of宏

/*根据结构体某成员计算结构体的首地址*/
#define  container_of(ptr, type, member)   ({\
                                           const typeof( ((type *)0) -> member ) *_mptr = (ptr);\
                                           (type *)( (char *)_mptr - offsetof(type, member) );})

container_of宏作用
根据结构体某成员变量计算结构体的首地址

container_of宏原理
ptr : 结构体成员地址

type : 结构体类型

member : 结构体成员变量

const typeof( ((type *)0) -> member ) *_mptr = (ptr);该语句表示使用结构体类型的指针指向成员member,进而获取结构体成员member的类型,使用该类型定义一个指针 _mptr保存结构体的成员地址ptr。

(type *)( (char *)_mptr - offsetof(type, member) );该语句表示把 _mptr强制转换为char *类型减去member在结构体中的偏移量即可获取首地址,再把获取到的首地址强制转换为结构体类型的指针返回。

该宏为语句表达式,语句表达式的返回值为最后一条语句的结果,因此container_of宏返回的是结构体类型的指针,指向结构体的首地址。

示例

#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 student
{
   int age;
   int num;
   int math;
};

int main(void)
{
   /*初始化结构体成员*/
   struct student stu = {10, 20, 30};

   /*定义指针ptr指向结构体中的num成员地址*/
   int *ptr = &stu.num;

   /*保存结构体的首地址*/
   struct student *header_add = NULL;

   /*计算结构体的首地址*/
   header_add = container_of(ptr, struct student, num);

   /*打印成员num在结构体中的偏移量*/
   printf("num offsetof in stu = %d\r\n", offsetof(struct student, num));

   /*打印container_of返回的结构体首地址*/
   printf("container_of header_add = %#p\r\n", header_add);

   /*直接打印结构体的首地址*/
   printf("stu header_add = %#p\r\n", &stu);

   /*根据计算出来的结构体首地址指向结构体的其他成员*/
   printf("header_add -> math = %d\r\n", header_add -> math);

   return 0;
}

上述代码运行后输出如下:

num offsetof in stu = 4

container_of header_add = 0X0061FEB8

stu header_add = 0X0061FEB8

header_add -> math = 30
可以发现使用container_of计算出来的结构体首地址和直接打印出来的结构体首地址相同,表示该宏可以获取结构体的首地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值