这个宏/指针声明在做什么?

时间:2017-05-15 17:28:39

标签: c pointers

任何熟悉此宏定义的人:

#define CrashData                     (*((CRASH_DATA *)CRASHDATA_ADDRESS))

,其中

CRASH_DATA  is a typedef struct
CRASHDATA_ADDRESS is 0xF3F80UL

我怀疑我们正在创建一个名为CrashData的结构变量,该变量是从addrees放置到右前进的?

感谢您的帮助,Pointer声明令人困惑。

2 个答案:

答案 0 :(得分:2)

  

我怀疑我们正在创建一个名为CrashData的结构变量,该变量是从addrees放置到右前进的?

不,不完全是。

首先,在任何地方都没有变量。当您将代码称为宏定义时,您的说法正确;因此,代码定义了一个名为CrashData,它与变量完全不同。

因此,让我们看一下宏观的替换文字:

(*((CRASH_DATA *)CRASHDATA_ADDRESS))
  • 从内部开始,您声称CRASHDATA_ADDRESS 0xF3F80UL,我将其解释为意味着它实际上是一个宏,{{1}常量作为替换文本。

  • unsigned long只能是强制转换运算符,因此听到(CRASH_DATA *)CRASH_DATA ed类型别名,或者可能是扩展到此类的宏,这并不足为奇。演员表的结果是指向typedef的指针。 可能特别指向CRASH_DATA指定的地址处的内存块,但标准仅表示

  

结果是实现定义的,可能没有正确对齐,   可能不会指向引用类型的实体,并且可能是a   陷阱表示。

  • 演员表的结果括在括号中,并且取消引用操作符(一元CRASHDATA_ADDRESS)将应用于它。取消引用指针的结果是指定指针指向的对象的左值。

  • 取消引用的结果括在括号中,这些括号服务于普通的分组角色。这很有用,因此在使用宏时,运算符优先级不会产生令人惊讶的效果。

总的来说,宏的意图似乎是表示一个表达式,它表示一个从*开始的内存块,就好像它是{{1}类型的对象一样}}。由于CRASHDATA_ADDRESS是结构类型,因此您可以通过CRASH_DATA运算符访问其成员:

CRASH_DATA

虽然如果.是一个变量,你可能会编写类似的代码,但它不是一个变量,并且它的行为方式与变量不同。

答案 1 :(得分:0)

首先,((CRASH_DATA *)(CRASHDATA_ADDRESS))是一个类型转换,告诉编译器将CRASHDATA_ADDRESS中定义的地址视为指向CRASH_DATA类型项的指针。

接下来,star(*)运算符将取消引用指针。由于它是指向结构的指针,因此一旦引用,您就可以通过点(。)运算符访问任何结构的成员。

您应该能够访问这样的数据:

CrashData.some_struct_member

无论如何,重要的是要明白你不是在创造'一个新的struct变量,你只是告诉编译器将存储在内存地址0xF3F80UL的数据视为CRASH_DATA类型的变量。