EDKII CR宏:根据成员指针获取父结构体变量指针

核心提示:

1. CR宏 (Containing Record):根据成员指针获取父结构体变量指针

2. 0 指针的妙用。

在EDKII 的代码中有不少关于CR宏的使用,如 时钟中断处理函数CoreTimerTick。

VOID EFIAPI CoreTimerTick (  IN UINT64   Duration  ) {
  IEVENT          *Event;
   ...
  if (!IsListEmpty (&mEfiTimerList)) {
    Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);
   ...  }
}

CR宏的定义

  1. //  CONTAINING_RECORD - returns a pointer to the structure
  2. //      from one of it‘s elements.
  3. #define_CR(Record, TYPE, Field)  ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
  4. #defineCR(Record, TYPE, Field, Signature)   \\par     _CR(Record, TYPE, Field)

CR的用法:  _CR (  结构体某成员变量的指针 Record, 结构体类型定义 TYPE, 结构体成员变量名 Field  );

这个宏定义的关键点是 0 指针。 结构体调用 Struct –> Member 是 把Struct的指针 加上 Member的偏移量, 0->member的调用可以直接得到 member的偏移量。 这样把member的实际指针 减去 偏移量,就是这个结构体本身的指针。 很巧妙的用法!

下面举例说明:

CR宏的使用

  1. #include"stdafx.h"
  2. #define  CHAR8  char
  3. //  CONTAINING_RECORD - returns a pointer to the structure
  4. //      from one of it‘s elements.
  5. #define_CR(Record, TYPE, Field)  ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
  6. #defineCR(Record, TYPE, Field, Signature)   \\par     _CR(Record, TYPE, Field)
  7. typedefstruct_MyStruct
  8. {
  9. inta;
  10. charb;
  11. longc;
  12. intd;
  13. } MyStruct;
  14. int_tmain(intargc, _TCHAR* argv[])
  15. {
  16. MyStructmyStruct = {10,‘a‘,30,25};
  17. printf("MyStruct Address 0x%x \n", &myStruct);
  18. MyStruct * pMyStruct = CR(&(myStruct.c), MyStruct, c, NULL);
  19. printf("pMyStruct Address 0x%x \n", pMyStruct);
  20. getchar();
  21. return 0;
  22. }
时间: 2024-11-08 19:15:37

EDKII CR宏:根据成员指针获取父结构体变量指针的相关文章

C语言中宏的运用------利用宏技术可以简化对某结构体变量的访问

利用宏技术可以简化对某结构体变量的访问 有时候,为了方便访问结构变量中的某个元素,我们可以利用宏去进行代码的替换. #include<stdio.h>#include<stdlib.h> struct data{ int len; int show;}; struct data Data;#define LEN Data.len  //为了访问而定义的宏 int main(){ LEN = 5; printf("%d\n",Data.len); Data.len

指针 指针与数组 指针与字符串 指针与函数 结构体与指针 宏

指针 指针与数组 指针与字符串 指针与函数?? 指针与数组 1.数组名:数组元素首地址 eg: int array[3]={1,3,6}; 这里array 恒等于&array[0] 2.int *p = a; int *p = 0; int a[]={0}; 3.int *p = a; 均指向数组的首地址 *p是? *(p+1)是?(*p)+1是? *(p+1)决定向下移动几个字节是类型 4.指针可以当数组名使用 p[1] = 3; 恒等于a[1] ;恒等于*(p+1);恒等于*(a+1) 5.

c++指向结构体变量指针

转自http://www.jb51.net/article/42140.htm 定义: 结构体变量的指针就是该变来那个所占据的内存段的起始地址.可以设一个指针变量,来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址. 设p是指向结构体变量的数组,则可以通过以下的方式,调用指向的那个结构体中的成员: (1)结构体变量.成员名.如,stu.num. (2)(*p).成员名.如,(*p).num. (3)p->成员名.如,p->num. 代码如下: #include<iostrea

结构体指针数组和结构体数组指针的区别

对于初学者的我来说,面对又是数组又是结构体还有指针,一下子就蒙了,在网上查找资料也没有相应的介绍,经过我的测试终于明白了其中的猫腻:结构体数组指针 *[]struct:结构体数组指针的指针是数组的指针,即表示数组的地址,数组里面存放的是结构体类型结构体指针数组 []*struct:即指针表示结构体的地址,数组里面存放的是结构体的指针有什么解释不对的地方请指正 代码测试:package mainimport ( "fmt") type XCDataStu struct { Id int

c语言指针数组和结构体的指针

指向数组的指针,先初始化一个数组,使用传统方式遍历 1 void main() 2 { 3 int a[5] = { 1,2,3,4,5 }; 4 for (int i = 0; i < 5; i++) 5 { 6 printf("%d,%x\n", a[i], &a[i]); 7 printf("%d,%x\n",*(a+i),a+i); //等价 a[i] , &a[i] 8 } 9 } a就是数组a的首地址,即元素1的地址, a + 1

黑马程序员 C语言-枚举,结构体,指针

一.枚举 ※枚举变量的定义 前面只是定义了枚举类型,接下来就可以利用定义好的枚举类型定义变量. 跟结构体一样,有3种方式定义枚举变量 1.先定义枚举类型,再定义枚举变量 enum Season {spring, summer, autumn, winter}; enum Season s; 2.定义枚举类型的同时定义枚举变量 enum Season {spring, summer, autumn, winter} s; 3.省略枚举名称,直接定义枚举变量 enum {spring, summer

指向结构体的指针

运用指向结构体数组的指针输出学生信息 说明:指针指向结构体数组,就得到了该结构体数组的起始地址.通过该地址可以访问结构体数组中的所有成员变量.其中,指向结构体的指针的算术运算与 指向数组的指针的用法相似. #include<stdio.h> #define N 10 //结构体类型及变量的定义,初始化 struct student { char *number; char *name; char sex; int age; float score; }stu[3]={{"06001&

C语言 指向结构体变量的指针

一个指向变量的指针表示的是占内存中起始位置 一个指向结构体的变量的指针表示的是这个结构体变量占内存中的起始位置,同样它也可以指向结构体变量数组 定义结构体变量的指针: //假设已有一个结构体名为Student struct Student *pStruct // 结构体类型 * 指针名; 通过指针来引用结构体中的成员,有三种方式 demo: 1 # include <stdio.h> 2 # include <stdlib.h> 3 /* 4 1.使用->引用结构体成员 5

在Golang里如何实现结构体成员指针到结构体自身指针的转换

原文地址:http://goworldgs.com/?p=37 在C语言中有一个经典的宏定义,可以将结构体struct内部的某个成员的指针转化为结构体自身的指针.下面是一个例子,通过FIELD_OFFSET宏计算结构体内一个字段的偏移,函数getT可以从一个F*的指针获得对应的T*对象. struct F { int c; int d; } struct T{ int a; int b; struct F f; } #define FIELD_OFFSET(type, field) ((int)