volatile关键字的作用是什么?在c++中它能解决什么问题?

就我而言,我从来没有明知肚明地需要它。


当前回答

我曾经在20世纪90年代早期开发过一个大型应用程序,其中包含使用setjmp和longjmp进行基于c语言的异常处理。volatile关键字对于那些值需要保存在作为“catch”子句的代码块中的变量是必要的,以免这些变量被存储在寄存器中并被longjmp清除。

其他回答

volatile关键字的目的是防止编译器对可能以编译器无法确定的方式改变的对象应用任何优化。

声明为volatile的对象在优化中被省略,因为它们的值可以被当前代码范围之外的代码随时更改。系统总是从内存位置读取volatile对象的当前值,而不是在请求时将其值保存在临时寄存器中,即使之前的指令从同一对象中请求一个值。

考虑以下情况

1)由中断服务例程在作用域外修改的全局变量。

2)多线程应用程序中的全局变量。

如果不使用volatile限定符,可能会出现以下问题

1)当优化被打开时,代码可能不会像预期的那样工作。

2)当中断被启用和使用时,代码可能不会像预期的那样工作。

Volatile:程序员最好的朋友

https://en.wikipedia.org/wiki/Volatile_ (computer_programming)

我曾经在20世纪90年代早期开发过一个大型应用程序,其中包含使用setjmp和longjmp进行基于c语言的异常处理。volatile关键字对于那些值需要保存在作为“catch”子句的代码块中的变量是必要的,以免这些变量被存储在寄存器中并被longjmp清除。

除了volatile关键字用于告诉编译器不要优化对某些变量(可以由线程或中断例程修改)的访问之外,它还可以用于删除一些编译器错误——是的,它可以是——。

例如,我在一个嵌入式平台上工作,编译器对变量的值做出了一些错误的假设。如果代码没有优化,程序可以正常运行。通过优化(这是非常必要的,因为这是一个关键的例程),代码将无法正常工作。唯一的解决方案(虽然不是很正确)是将“错误的”变量声明为volatile。

一些处理器具有超过64位精度的浮点寄存器(例如。32位x86没有SSE,见Peter的评论)。这样,如果您对双精度数运行多次操作,实际上会得到比将每个中间结果截断为64位更高精度的答案。

这通常很好,但这意味着根据编译器如何分配寄存器和进行优化,对于完全相同的输入,完全相同的操作将得到不同的结果。如果您需要一致性,那么您可以使用volatile关键字强制每个操作返回内存。

它对于一些没有代数意义但减少浮点误差的算法也很有用,比如Kahan求和。代数上它是一个nop,所以它经常会被错误地优化除非一些中间变量是不稳定的。

你的程序似乎工作,即使没有挥发关键字?也许这就是原因:

如前所述,volatile关键字有助于以下情况

volatile int* p = ...;  // point to some memory
while( *p!=0 ) {}  // loop until the memory becomes zero

但是,一旦调用外部函数或非内联函数,似乎几乎没有任何影响。例如:

while( *p!=0 ) { g(); }

然后无论是否使用volatile都会产生几乎相同的结果。

只要g()可以完全内联,编译器就可以看到正在发生的一切,因此可以进行优化。但是,当程序调用一个编译器看不到发生什么的地方时,编译器再做任何假设就不安全了。因此,编译器生成的代码总是直接从内存中读取。

但是要注意,当函数g()变成内联(由于显式更改或由于编译器/链接器的聪明)时,如果您忘记volatile关键字,那么您的代码可能会崩溃!

因此,我建议添加volatile关键字,即使您的程序似乎没有它也可以工作。它使意图在未来的变化方面更加清晰和强大。