volatile关键字的作用


volatile关键字


volatile关键字是C/C++众多关键字中的一个,但不常用。

我们知道,为了提高程序程序执行的效率。大多数编译器都会对齐进行优化。优化级别由低到高分为:-O0~ -O3。

但有时候,编译器的这种优化也会导致内存和CPU(寄存器)中数据不一致的问题,volatile关键字就是用来解决这种问题的。


Code


接下来我们以linux中的gcc编译器为例,编写一段代码证明volatile关键字的作用。

1.编写一段flag死循环的代码(编译器无优化)

代码:捕捉2号信号并在handler函数里修改flag值

1

运行程序并CTRL+C捕捉到2号信号时flag置为1,此时flag写入内存,while循环不成立。所以程序退出。

2

2.编译器优化产生数据二义性问题
代码:用gcc myvol.c -O3命令加上编译器优化,使得main函数中的flag放在寄存器中。

3
运行程序,由于加了优化,此时另一个执行流handler在内存中更改flag的值编译器就不能察觉了,因为他会直接从寄存器中读数据。所以再次CTRL+C时,程序就不会退出了。

3.volatile取消编译器优化

代码:在程序中加入volatile关键字,取消编译器优化。

4

运行程序,代码退出。

5


The End


其实上述问题并非是编译器优化错误

设想一下,如果程序只有单一的执⾏流程,只要当前执行流程没有改变flag的值,那它就没有理由会变,不需要反复从内存读取。所以编译器优化之后省去了每次循环读内存的操作,效率⾮常⾼。

所以不能说编译器做错了,只能说编译器无法识别程序中存在多个执行流。之所以程序中存在多个执行流程,是因为调用了特定平台上的特定库函数。这些不是C/C++语言本身的规范,不归编译器管,所以不应该编译器来背锅。

程序员应该自己处理这些问题。所以C语⾔提供了volatile限定符,这样即使指定了优化选项,编译器也不会优化掉对变量flag内存单元的读写。

但对于程序中存在多个执行流程访问同一全局变量的情况,volatile限定符是必要的。此外,虽然程序只有单⼀的执行流程,但是变量属于以下情况之一的,也需要volatile限定:

1.变量的内存单元中的数据不需要写操作就可以自⼰发⽣生变化,每次读上来的值都可能不一 样 ,例如接收寄存器
2. 即使多次向变量的内存单元中写数据,只写不读,也并不是在做无用功,而是有特殊意义的。例如发送寄存器。
3. sig_atomic_t类型的变量应该总是加上volatile限定符,因为要使用sig_atomic_t类型的理由也正是要加volatile限定符的理由。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值