_CR(Record, TYPE, Field)

来源:互联网 发布:什么是数据库中的事物 编辑:程序博客网 时间:2024/06/03 21:50

在看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个字节。






0 0
原创粉丝点击