我发现一个网站上的这个片段:C语言:如何解释这个#define?
#define DISPLAY_CR (*(volatile unsigned int *) 0x4000000)
DISPLAY_CR = somevalue;
是应该描述DISPLAY_CR作为挥发性unsigned int的指针ADRESS 0x4000000
我不明白的是为什么:
- 双括号叠瓦?
- 两颗星使用(为什么两颗星,而不是只有一个?)
我发现一个网站上的这个片段:C语言:如何解释这个#define?
#define DISPLAY_CR (*(volatile unsigned int *) 0x4000000)
DISPLAY_CR = somevalue;
是应该描述DISPLAY_CR作为挥发性unsigned int的指针ADRESS 0x4000000
我不明白的是为什么:
额外的括号中宏的标准做法。宏以复制和粘贴的方式进行扩展,因此如果没有括号,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
其希望应该是清晰的。
额外括号是从由周围的令牌被破坏停止宏。 的“明星”是要用到的地址转换为指针,然后取消对它的引用,其地址
你有
0x4000000
来获取值 - 地址0x4000000(volatile unsigned int *) 0x4000000
- 铸易失性指针* (volatile unsigned int *) 0x4000000
- 取消引用指针,使一个左(*(volatile unsigned int *) 0x4000000)
- 包裹在一组额外的支架,使DISPLAY_CR
是有效罪GLE令牌 - 你不会陷入运算符优先级的问题等周围谢谢你这个有用的一步一步的解释:) – loloof64 2012-02-13 14:09:06
这个宏没有描述DISPLAY_CR
作为挥发性unsigned int的指针地址0x4000000
。它描述DISPLAY_CR
为无符号整数值位于0x4000000
,最有可能的,特定于硬件的寄存器。
你需要volatile
的原因是为了防止编译器“优化”多次写入硬件寄存器。例如,如果你需要将其值设置为1,然后将其清除信号的东西到硬件,你可以写
DISPLAY_CR = 1;
DISPLAY_CR = 0;
没有volatile
编译器可能下降的第一项任务是微不足道的; volatile
阻止它这样做。
谢谢你的易变的“用例”:) – loloof64 2012-02-13 14:26:48
星形的内部意味着该类型是指针unsigned int类型。外星取消指向它指向的内存单元的指针。
OK,让我们打破下来。
显然,0x4000000
是一个数字,我们希望用它来指定一个特定的内存地址(希望这里有重要的东西)。
现在,是铸造,这意味着它告诉编译器来强制参数的类型为指定的类型(这是指针为无符号整数,易失性)。
最后,*
是解引用运算符。这意味着我们要访问存储在该地址中的值。
使用宏时,额外的括号只是很好的风格 - 由于运算符优先规则有点令人困惑,C程序员特别对它们是防御性的。
围绕整个表达式的括号对于所有的宏都很重要,并且对于像所列出的那样的宏来说是至关重要的。
如果有人写,说:
int foo = DISPLAY_CR++;
,并且没有括号包围的宏,这将作为解析:
int foo = *(volatile unsigned int *)(0x4000000++);
它有一个完全不同的含义。
谢谢:)那么两颗星呢:为什么两颗星? – loloof64 2012-02-13 14:01:40
好吧,这很清楚:)非常感谢:) – loloof64 2012-02-13 14:07:55