volatile
关键字告诉编译器不要优化带前缀的变量。变量可能在运行时由未知源(编译器不知道)可能由外部中断等改变。
volatile
还有其他优势吗?
volatile
是否适用于从文件中读取?
答案 0 :(得分:7)
volatile
关键字表示编译器没有优化前缀的变量,变量可能在运行时由未知源(编译器不知道)改变,可能是外部中断等。
没有。 volatile
关键字不会告诉编译器禁用或不优化变量; volatile
关键字告诉编译器可以在程序外部修改变量(或者更改代表的内存)。
这导致编译器不再能够进行必要的分析以确定各种优化是否安全(在功能上是等效的),因此编译器不会执行这些优化。这是一个必要的副作用,但不是关键字存在的主要目的。
使用volatile
作为一种稍微或稍微可移植的黑客,像pragma
一样禁用编译器的优化是一种相当常见的模式。在嵌入式编程之外,这可能是应用程序编程人员最常遇到的用法。
编译器知道该控制器的所有中断。那么在这种情况下
volatile
关键字如何帮助?
volatile
关键字表示可以在程序控制之外修改存储器内容,可以在另一个进程,线程或外部信号(如硬件中断)中进行修改。
编译器不知道"关于中断,可能存在与编译器一起分发的系统头文件,该编译器为中断定义符号名称,但这并不意味着编译器理解它们。
volatile
还有其他优势吗?
除了这里描述的内容之外,我不能想到。
[是]
volatile
appl [y]从文件中读取?
除了用作进程间通信(IPC)或信号量的形式外,文件的内容通常由单个进程控制,因此不需要使用volatile
。
答案 1 :(得分:5)
volatile
实际上告诉编译器变量的值可以在其控制流之外的中更改。最流行的是中断或中断处理程序或硬件寄存器。对于后者,编译器确实不知道其值何时发生变化。它也不适用于中断,因为它只发生在运行时。
请注意,C假定单线程程序流程;编译器不知道并发进程。它对底层硬件的假设就更少了。
对于所有其他变量,编译器可能(gcc,例如实际将)假设它完全了解系统状态。
对volatile
变量的访问也可能不会相互重新排序。这在例如UART需要首先读取状态寄存器,然后可以将新的字符存储到发送数据寄存器中。对于大多数MCU,只有这个序列才能正确清除标志。非常重要:非易失性变量可以重新排序,就像编译器想要的那样(当然,只要它不改变程序逻辑)。
请注意,volatile
不保证多核系统的原子性和正确行为,或者确保防止硬件(内存控制器等)对访问的重新排序(好吧,AVR有点不合适所有这些 ;-)。这就是锁定的一个原因,以及为什么内存映射中的硬件区域被硬件特殊处理(有序,非共享)。
修改强>
Here详细说明了gcc如何处理易失性对象。众所周知,gcc严格遵守优化标准。任何不被禁止的东西都可能被利用来进行优化。像IAR这样的经典嵌入式编译器通常要保守得多。
答案 2 :(得分:4)
volatile的C / C ++标准意味着对volatile变量的读写将是对内存中该位置的读取或写入,并且将保持对volatile变量的操作顺序。由于从volatile变量读取实际上是在内存中读取变量,因此如果变量由外部源(如另一个线程,进程或硬件)更新,则读取的值将反映在读取之前发生的任何写入。它旨在用于内存映射硬件接口,例如I / O内存映射端口。它不会阻止对其他变量的无序操作。我假设维护了多个volatile变量的操作顺序,因为硬件/软件握手需要这样做。
Microsoft编译器可选地扩展volatile的含义,以便对volatile变量的读/写操作有效地完成memory barrier,并可用于线程之间的通信。 MSDN volatile。
答案 3 :(得分:1)
volatile
保证编译器不会对变量执行任何优化。如果变量的值在编译器确定的范围内没有更改,则可以将值缓存到寄存器并引用该缓存值以提高效率,这样就不会浪费周期来获取实际值来自主存的价值。
我想在具有如此有限数量的寄存器的微控制器中,您不希望不断地缓存变量。