结构体中两个重要的宏

offsetof宏:

通过前面的学习,我们知道通过结构体整体变量来访问其中的各个元素,在本质上是通过指针的方式来访问的,在形式上通过 . 的方式来访问的(实际上是编译器自动计算了偏移量)

offsetof宏的作用:通过这个宏来计算结构体中某个元素和结构体首地址的偏移量

offsetof宏的原理:我们虚拟一个type类型结构体的变量,然后用type.member的方式来访问member元素,继而得到了member相对于整个变量首地址的偏移量

offsetof宏:

//offsetof宏:这个宏的返回值是member元素相对于整个结构体变量的首地址的偏移量,类型是int
//type是结构体类型 , member是结构体中的一个元素名
#define  offsetof(type,member)   ((int) &((type *)0)->member)

offsetof宏的学习思路:对应指针和结构体不是很熟练的同学很难看到这个宏,第一我们先学会怎么使用offsetof宏,第二在去理解offsetof是怎么实现计算结构体的偏移量的。

offsetof宏解析:

offsetof实现方式类似于我下面的代码,就是通过减法计算出偏移量,要记住在offsetof宏中的被减数永远结构体的首地址。

    printf("&s1的首地址为:%p\r\n", &s1);
	printf("&s1.b地址为:%p\r\n", &s1.b);
	printf("偏移量是:%d\r\n", (int)&(s1.b) - (int)(&s1));

下面我一步步解析offsetof这个宏

(type *)0:

这是一个强制类型转换,把0地址强制类型转换成一个指针,这个指针指向一个type类型的结构体变量(这个type的结构体可能存在也可能不存在,但是只要我们不去解引用这指针就不会出错)

((type *)0->member):

(type * )0是一个type类型的结构体变量的指针,通过指针的来访问这个结构体变量的member

&((type *)0->member):

&((type * )0->member)解剖的一个过程是:(type *)0 ->member >&((type *)0->member),目的就是得到member元素的地址,因为整个结构体变量的首地址是0

container_of宏:

container_of宏的作用:

知道结构体中的某个元素的指针,反推这个结构体变量的指针。通过container_of宏,我们可以从一个元素的指针得到整个结构体变量的指针(结构体的首地址),继而得到结构体其他元素的指针

container_of宏的原型:
#define container_of(ptr, type, member) ({	\
   typeof( ((type *)0)->member ) *__mptr = (ptr);  \
   (type *)( (char *)__mptr - offsetof(type,member) );})

container_of宏的解析:

typeof关键字的作用:typeof(a)时通过变量a得到a的数据类型
container_of宏的原理:先通过typeof关键字得到member元素的类型定义成一个指针,然后用这个指针减去该元素相对与整个结构体变量的偏移量(通过offsetof宏得到的),减去之后得到的就是整个结构体的是首地址,再把这个地址强制转类型转换成type*即可。

typeof( ((type *)0)->member ) *__mptr = (ptr): 首先定义了一个临时的数据类型(通过 typedef(((type *)0)->member)获得)与ptr相同的指针变量_mptr,然后用它来保存ptr的值

用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)

学习指南:

最基本的要求:必须会这两个宏的使用,能看到别人使用这个宏的时候是什么意思
进一步要求:能理解这两宏的工作原理,表述出来。(这个得慢慢来)
更高级要求:能写出这两个宏。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值