_CR(Record, TYPE, Field)

在看EDKII的code时遇到一个宏,琢磨了好一阵,写下来和大家分享。如有错误欢迎指出。宏如下:

#define   _CR(Record, TYPE, Field)   ((TYPE *)  ((CHAR8 *)  (Record)  -  (CHAR8 *)  &(((TYPE *) 0) ->Field)))


底层code中会有各种结构体,这个宏的作用就是在已知某结构体变量成员的地址时逆向求出该结构体变量的基地址。中Record指结构体变量成员的地址,TYPE指结构体类型,Field指结构体变量成员。


&(((TYPE *) 0)->Field)是该宏的逆天之处,我等菜鸟由衷赞叹。

(TYPE *)是强制类型转换,((TYPE *) 0)是将数值0强制转换为指向TYPE数据类型的指针,相当于新定义一个(TYPE *)指针并将指针赋初值为0 !!!

&(((TYPE *) 0)->Field)是取该结构体变量Field成员的地址(用结构体指针运算符来访问结构体成员)。因为这个结构体变量的基地址为0,所以Field的地址就等于Field相对于该结构体变量基地址的偏移。

结论:&(((TYPE *) 0)->Field)是Field相对于该结构体变量基地址的偏移。


接下来连起来看 ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *)0)->Field)))

Record上边有说是Field的地址,&(((TYPE *)0)->Field)是Field相对于该结构体变量基地址的偏移,所以((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field))即该结构体变量的基地址,再经(TYPE *)强制转换就变成了指向TYPE变量的地址 。这里有一个强制类型转换(CHAR8 *) ,地址在相减之前都转换成了CHAR8类型,为什么这样?因为指针的移动是分粒度的,两个(CHAR8*)相减数值是多少地址就是多少,若是两个(UINT64*)相减,数值要乘以8才等于地址值,UINT64占8个字节。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值