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


当前回答

正如这里许多人正确地建议的那样,volatile关键字的流行用途是跳过volatile变量的优化。

在阅读了volatile之后,我想到的最好的优点是——在longjmp的情况下防止回滚变量。非本地跳转。

这是什么意思?

它只是意味着在你进行堆栈展开后,最后一个值将被保留,以返回到前一个堆栈帧;通常是在一些错误的情况下。

因为它超出了这个问题的范围,所以我不打算在这里详细讨论setjmp/longjmp,但是值得一读;以及如何使用波动特征来保留最后的价值。

其他回答

volatile的另一个用途是信号处理程序。如果你有这样的代码:

int quit = 0;
while (!quit)
{
    /* very small loop which is completely visible to the compiler */
}

编译器可以注意到循环体没有触及quit变量,并将循环转换为while (true)循环。即使在信号处理程序上为SIGINT和SIGTERM设置了退出变量;编译器无法知道这一点。

但是,如果quit变量被声明为volatile,编译器将被迫每次加载它,因为它可以在其他地方修改。这正是你在这种情况下想要的。

在Dennis Ritchie设计的语言中,除了地址未被获取的自动对象外,对任何对象的每次访问都表现为计算对象的地址,然后在该地址上读写存储。这使得该语言非常强大,但严重限制了优化机会。

While it might have been possible to add a qualifier that would invite a compiler to assume that a particular object wouldn't be changed in weird ways, such an assumption would be appropriate for the vast majority of objects in C programs, and it would have been impractical to add a qualifier to all the objects for which such assumption would be appropriate. On the other hand, some programs need to use some objects for which such an assumption would not hold. To resolve this issue, the Standard says that compilers may assume that objects which are not declared volatile will not have their value observed or changed in ways that are outside the compiler's control, or would be outside a reasonable compiler's understanding.

Because various platforms may have different ways in which objects could be observed or modified outside a compiler's control, it is appropriate that quality compilers for those platforms should differ in their exact handling of volatile semantics. Unfortunately, because the Standard failed to suggest that quality compilers intended for low-level programming on a platform should handle volatile in a way that will recognize any and all relevant effects of a particular read/write operation on that platform, many compilers fall short of doing so in ways that make it harder to process things like background I/O in a way which is efficient but can't be broken by compiler "optimizations".

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

Volatile(计算机编程)

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

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

正如这里许多人正确地建议的那样,volatile关键字的流行用途是跳过volatile变量的优化。

在阅读了volatile之后,我想到的最好的优点是——在longjmp的情况下防止回滚变量。非本地跳转。

这是什么意思?

它只是意味着在你进行堆栈展开后,最后一个值将被保留,以返回到前一个堆栈帧;通常是在一些错误的情况下。

因为它超出了这个问题的范围,所以我不打算在这里详细讨论setjmp/longjmp,但是值得一读;以及如何使用波动特征来保留最后的价值。

Volatile也很有用,当你想强制编译器不优化特定的代码序列时(例如编写一个微基准测试)。