volatile详解
volatile——易变的,大部分人都知道它的作用是确保本条指令不会被编译器的优化而忽略。在这里举几个例子进行解释。
1 | int main() |
例如在这种情况时,多次使用了i变量,编译器可能会对其进行优化,第一次在使用这个变量时,它会去读内存,把这个变量的值读进CPU的某个寄存器,在后面的使用中,它一直去通过读这个寄存器获取变量的值,但是这个值是这个变量最原始的值,它并没有每次去内存中读这个变量,去更新这个值,这样就会出现一些问题,尤其是对于嵌入式而言。
场景一:中断服务程序中修改的供其它程序检测的变量
当变量在触发某中断程序中修改,而编译器判断主函数里面没有修改该变量,因此可能只执行一次从内存到某寄存器的读操作,而后每次只会从该寄存器中读取变量副本,使得中断程序的操作被短路。
场景二:多任务环境下各任务间共享的标志
在某个任务中,编译器对变量进行优化,把这个变量的值读进CPU的某个寄存器,在后面的使用中,它通过读这个寄存器获取变量的值,但是在另一个任务中,改变了这个变量的值,但是这个寄存器的值并不会进行改变,从而造成应用程序读取的值和实际的变量值不一致。
场景三:存储器映射的硬件寄存器
假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。for(i=0;i< 10;i++) *output = i;前面循环半天都是废话,对最后的结果毫无影响,因为最终只是将output这个指针赋值为9,省略了对该硬件IO端口反复读的操作。
总结
volatile应该解释为“直接存取原始内存地址”相对于“易变的”更合适,volatile对应的变量可能在你的程序本身不知道的情况下发生改变。
什么时候一定要将变量定义为volatile?
- 寄存器变量
- 被中断历程使用的全局变量
- 被多个线程使用的全局变量
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 VAEF!
评论






