易变量
volatile
关键字告诉编译器,由于外部条件,变量的值可能随时发生变化,而不仅仅是程序控制流的结果。
编译器不会优化与 volatile 变量有关的任何内容。
volatile int foo; /* Different ways to declare a volatile variable */
int volatile foo;
volatile uint8_t * pReg; /* Pointers to volatile variable */
uint8_t volatile * pReg;
使用 volatile 变量有两个主要原因:
- 与具有内存映射 I / O 寄存器的硬件接口。
- 使用在程序控制流程外修改的变量时(例如,在中断服务程序中)
我们来看看这个例子:
int quit = false;
void main()
{
...
while (!quit) {
// Do something that does not modify the quit variable
}
...
}
void interrupt_handler(void)
{
quit = true;
}
允许编译器注意 while 循环不修改 quit
变量并将循环转换为无限的 while (true)
循环。即使在 SIGINT
和 SIGTERM
的信号处理程序上设置了 quit
变量,编译器也不知道。
将 quit
声明为 volatile
将告诉编译器不优化循环,问题将得到解决。
访问硬件时会出现同样的问题,如本例中所示:
uint8_t * pReg = (uint8_t *) 0x1717;
// Wait for register to become non-zero
while (*pReg == 0) { } // Do something else
优化器的行为是读取变量的值一次,不需要重新读取它,因为值总是相同的。所以我们最终得到了一个无限循环。为了强制编译器执行我们想要的操作,我们将声明修改为:
uint8_t volatile * pReg = (uint8_t volatile *) 0x1717;