如果我们在每次更新新值时将变量声明为volatile
如果我们将一个变量声明为 const
那么该变量的值将不会改变
然后 const volatile int temp;
像上面那样声明变量temp
有什么用?
如果我们声明为 const int temp
会发生什么?
最佳答案
标记为 const volatile
的对象将不允许被代码更改(由于 const
限定符会引发错误)- 至少通过那个特定名称/指针。
限定符的 volatile
部分意味着编译器无法优化或重新排序对对象的访问。
在嵌入式系统中,这通常用于访问硬件寄存器,这些寄存器可以由硬件读取和更新,但写入没有意义(或者写入可能出错)。
一个例子可能是串行端口的状态寄存器。各种位将指示字符是否正在等待读取或发送寄存器是否准备好接受新字符(即 - 它为空)。每次读取此状态寄存器都可能产生不同的值,具体取决于串行端口硬件中发生的其他情况。
写入状态寄存器没有任何意义(取决于特定的硬件规范),但您需要确保每次读取寄存器都会导致实际读取硬件 - 使用来自前一个缓存的值read 不会告诉您硬件状态的变化。
一个简单的例子:
unsigned int const volatile *status_reg; // assume these are assigned to point to the
unsigned char const volatile *recv_reg; // correct hardware addresses
#define UART_CHAR_READY 0x00000001
int get_next_char()
{
while ((*status_reg & UART_CHAR_READY) == 0) {
// do nothing but spin
}
return *recv_reg;
}
如果这些指针没有被标记为volatile
,可能会出现一些问题:
- while 循环测试可能只读取状态寄存器一次,因为编译器可以假设它指向的任何内容都不会改变(while 循环测试或循环本身没有任何东西可以改变它)。如果您在 UART 硬件中没有字符等待时进入函数,您可能会陷入无限循环,即使收到字符也不会停止。
- 编译器可以将接收寄存器的读取移动到 while 循环之前 - 再次因为函数中没有任何内容表明
*recv_reg
被循环更改,所以没有理由这样做进入循环前无法读取。
volatile
限定符确保编译器不会执行这些优化。
关于c - const 和 const volatile 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4592762/