为什么C中需要挥发性?它的用途是什么?它会做什么?
当前回答
它有两个用途。这些在嵌入式开发中特别常用。
编译器不会优化使用volatile关键字定义的变量的函数 Volatile用于访问RAM、ROM等中的精确内存位置。这通常用于控制内存映射设备,访问CPU寄存器和定位特定的内存位置。
参见程序集清单示例。 回复:在嵌入式开发中使用C“volatile”关键字
其他回答
volatile的另一个用途是信号处理程序。如果你有这样的代码:
int quit = 0;
while (!quit)
{
/* very small loop which is completely visible to the compiler */
}
编译器可以注意到循环体没有触及quit变量,并将循环转换为while (true)循环。即使在信号处理程序上为SIGINT和SIGTERM设置了退出变量;编译器无法知道这一点。
但是,如果quit变量被声明为volatile,编译器将被迫每次加载它,因为它可以在其他地方修改。这正是你在这种情况下想要的。
volatile变量可以从编译代码的外部进行更改(例如,程序可以将volatile变量映射到内存映射寄存器)。编译器不会对处理易失性变量的代码应用某些优化——例如,它不会在不将其写入内存的情况下将其加载到寄存器。这在处理硬件寄存器时很重要。
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关键字阻止变量被优化。
例如:
bool usb_interface_flag = 0;
while(usb_interface_flag == 0)
{
// execute logic for the scenario where the USB isn't connected
}
从上面的代码中,编译器可能认为usb_interface_flag被定义为0,并且在while循环中它将永远为0。优化后,编译器会一直将其视为while(true),导致无限循环。
为了避免这种情况,我们将标志声明为volatile,我们告诉编译器这个值可能会被外部接口或程序的其他模块改变,也就是说,请不要优化它。这就是volatile的用例。