c - const 和 const volatile 之间的区别

标签 c embedded

如果我们在每次更新新值时将变量声明为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/

相关文章:

embedded - 如何确定嵌入式系统中的最大堆栈使用量?

c++ - 有没有人有书面证据确保函数中参数的定义方式与普通变量声明相同?

c - 在 C 中打印数组时出现段错误

c++ - UART STM32L0,奇偶校验位实现

c - 将平台特定代码与嵌入式外设驱动程序的通用逻辑代码分开

c - 如何在不影响其他位的情况下将 uint8_t 放在 uint16_t 中间

Promela 中的缓存模型

java.lang.UnsatisfiedLinkError Windows 上的 JNI 错误

c - 使用 C 和 Python 在终端中获取随机字符

c - C 编程如何在没有头文件的情况下工作?