C语言:如何解释这个#define?

时间:2012-02-13 13:58:18

标签: c pointers c-preprocessor

我在网站上找到了这个代码段:

#define DISPLAY_CR  (*(volatile unsigned int *) 0x4000000) 
DISPLAY_CR = somevalue;

应该将DISPLAY_CR描述为指向地址0x4000000的易失性无符号int指针

我不明白的原因是:

  • 双括号imbrication?
  • 这两颗星使用(为什么是两颗星而不仅仅是一颗?)

7 个答案:

答案 0 :(得分:6)

额外的括号是宏中的标准做法。宏以复制和粘贴的方式进行扩展,因此如果没有括号,precedence可能会根据上下文进行更改。

忽略额外的括号,您的代码将扩展为:

*(volatile unsigned int *) 0x4000000 = somevalue;

相当于:

volatile unsigned int *p = 0x4000000; // Treat this as the address of a volatile unsigned int
*p = somevalue; // Write to that address

希望更清楚。

答案 1 :(得分:2)

额外的括号是阻止宏被周围的令牌破坏。 'stars'用于将地址转换为指针,然后取消引用它,以获取其地址的值

答案 2 :(得分:2)

你有

  • 0x4000000 - 地址0x4000000
  • (volatile unsigned int *) 0x4000000 - 强制转换为易失性指针
  • * (volatile unsigned int *) 0x4000000 - 取消引用制作左值的指针
  • (*(volatile unsigned int *) 0x4000000) - 包含一组额外的括号,以便DISPLAY_CR实际上是一个单一的令牌 - 你不会遇到运算符优先级问题等等。

答案 3 :(得分:2)

整个表达式的括号对于所有宏都很重要,对于像列出的宏一样重要。

如果有人要写,请说:

int foo = DISPLAY_CR++;

并且没有括起宏的括号,它将解析为:

int foo = *(volatile unsigned int *)(0x4000000++);

具有完全不同的含义。

答案 4 :(得分:1)

此宏未将DISPLAY_CR描述为指向地址0x4000000的volatile unsigned int指针。它将DISPLAY_CR描述为位于0x4000000的无符号整数,最有可能是硬件专用寄存器。

您需要volatile的原因是为了防止编译器“优化”对硬件寄存器的多次写入。例如,如果您需要通过将值设置为1然后清除它来向硬件发出信号,那么您可以编写

DISPLAY_CR = 1;
DISPLAY_CR = 0;

如果没有volatile,编译器可能会将第一个赋值放在无关紧要的位置; volatile阻止它这样做。

答案 5 :(得分:0)

内部的星号表示该类型是指向unsigned int的指针。外星将指针指向它所指向的记忆单元。

答案 6 :(得分:0)

好的,让我们分解一下。

显然,0x4000000是一个数字,我们想用它来指定一个特定的内存地址(希望那里有重要的东西)。

现在,(volatile unsigned int *)强制转换,这意味着它告诉编译器强制将参数类型强制为指定类型(指向无符号整数的指针,volatile)

最后,*是解除引用运算符。这意味着我们想要访问存储在该地址中的值。

使用宏时,额外的括号只是好的风格 - C程序员特别防守它们,因为运算符优先级规则有点令人困惑。