为什么C中需要挥发性?它的用途是什么?它会做什么?


当前回答

它有两个用途。这些在嵌入式开发中特别常用。

编译器不会优化使用volatile关键字定义的变量的函数 Volatile用于访问RAM、ROM等中的精确内存位置。这通常用于控制内存映射设备,访问CPU寄存器和定位特定的内存位置。

参见程序集清单示例。 回复:在嵌入式开发中使用C“volatile”关键字

其他回答

维基上有关于volatile的所有信息:

Volatile(计算机编程)

Linux内核的文档也对volatile做了一个很好的标记:

为什么不应该使用“volatile”类型类

volatile变量可以从编译代码的外部进行更改(例如,程序可以将volatile变量映射到内存映射寄存器)。编译器不会对处理易失性变量的代码应用某些优化——例如,它不会在不将其写入内存的情况下将其加载到寄存器。这在处理硬件寄存器时很重要。

在我看来,你不应该对volatile期望太高。为了说明这一点,看看尼尔斯·派彭布林克(Nils Pipenbrinck)的高票数回答中的例子。

我想说,他的例子并不适用于volatile。Volatile只用于: 阻止编译器进行有用和理想的优化。这与线程安全、原子访问甚至内存顺序无关。

在这个例子中:

    void SendCommand (volatile MyHardwareGadget * gadget, int command, int data)
    {
      // wait while the gadget is busy:
      while (gadget->isbusy)
      {
        // do nothing here.
      }
      // set data first:
      gadget->data    = data;
      // writing the command starts the action:
      gadget->command = command;
    }

gadget->data = gadget->command = command之前的数据仅由编译器在编译后的代码中保证。在运行时,处理器仍然可能根据处理器架构对数据和命令分配进行重新排序。硬件可能会得到错误的数据(假设gadget映射到硬件I/O)。数据和命令分配之间需要内存屏障。

它不允许编译器自动改变变量的值。易失性变量用于动态使用。

Volatile告诉编译器你的变量可以通过其他方式被改变,而不是通过访问它的代码。例如,它可能是一个I/ o映射的内存位置。如果在这种情况下没有指定这一点,一些变量访问可以被优化,例如,它的内容可以保存在寄存器中,并且内存位置不会再次读入。