为什么C中需要挥发性?它的用途是什么?它会做什么?
当前回答
它不允许编译器自动改变变量的值。易失性变量用于动态使用。
其他回答
简单来说,它告诉编译器不要对特定变量做任何优化。映射到设备寄存器的变量由设备间接修改。在这种情况下,必须使用volatile。
我会提到另一个挥发物很重要的场景。
假设您为更快的I/O对文件进行内存映射,并且该文件可以在幕后更改(例如,该文件不在您的本地硬盘驱动器上,而是通过网络由另一台计算机提供)。
如果您通过指向非易失性对象的指针(在源代码级别)访问内存映射文件的数据,那么编译器生成的代码可以多次获取相同的数据,而您却不知道它。
如果该数据碰巧发生了变化,您的程序可能会使用两个或多个不同版本的数据,并进入不一致的状态。如果程序处理不受信任的文件或来自不受信任位置的文件,这不仅会导致程序的逻辑不正确行为,而且还会导致可利用的安全漏洞。
如果您关心安全性,这是一个需要考虑的重要场景。
volatile的边缘用法如下。假设你想计算一个函数f的数值导数:
double der_f(double x)
{
static const double h = 1e-3;
return (f(x + h) - f(x)) / h;
}
问题是由于舍入误差,x+h-x通常不等于h。想想看:当你减去非常接近的数字时,你会丢失很多有效的数字,这可能会破坏导数的计算(想想1.00001 - 1)
double der_f2(double x)
{
static const double h = 1e-3;
double hh = x + h - x;
return (f(x + hh) - f(x)) / hh;
}
但是根据您的平台和编译器开关的不同,该函数的第二行可能会被积极优化的编译器删除。所以你可以写
volatile double hh = x + h;
hh -= x;
强制编译器读取包含hh的内存位置,从而丧失最终的优化机会。
它不允许编译器自动改变变量的值。易失性变量用于动态使用。
维基上有关于volatile的所有信息:
Volatile(计算机编程)
Linux内核的文档也对volatile做了一个很好的标记:
为什么不应该使用“volatile”类型类