C语言 volatile的作用与使用场景

今天完成公司的任务,突然想起来在调试过程中遇到了一个问题是这样的:“我在主函数里面写了一个while(x)的循环,想在中断里面去改变这个变量x,以达到主函数里面退出while循环的目的。但是结果并不是这样的,我的代码一直停在了while循环里面。后面我咨询了一位大哥,然后他告诉我在变量i前面加上一个volatile。果然,代码运行和我的预期一样了”。代码如下

void main()
{
    unsigned char x = 1;
    while(x)
    {
    }
}

void USART1_IRQHandler(void)
{
    x = 0 ;
}

那么volatile到底是做什么的呢?查阅了几篇博客,总算是明白了其中的道道。

volatile的本意是“易变的”。因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据。当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。精确地说就是,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用valatile,则编译器将对所声明的语句进行优化。(简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错)

看两个例子:

1、如果你的程序是这样的。

int num = 0 ;
num = 1;
num = 2;

如上,你的编译器就会去去优化你的代码,可能被优化成这样:

int num = 0 ;
num = 2;

结果“num = 1;”这条指令就丢失了。

但是如果你加上了volatile,你的代码变成了这样:

volatile int num = 0 ;
num = 1;
num = 2;

那么你的编译器就不再会去优化你的代码,你编译出来的指令还是三条。

 

2、当你遇到博主上面的情况时,你也应该加上volatile。第二种使用volatile的情况就是,在某个函数中定义的变量可能在函数外面被改变的情况,你就应该加上volatile,保证每次都必须从内存中读取数据,而不能重复使用放在cache或寄存器中的备份。

这种情况,尤其是在单片机程序,需要在中断程序中,改变某个变量的时候,用的特别多。

 

3、当然还有其他一些使用volatile的情况,如,存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义。

#define __I volatile const /*!< defines 'read only' permissions */
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */

你看你很少见到volatile,但是你肯定见到过__O、__I、__IO,被这三个定义的变量,都是必须从内存中去读值的。

 

好,说完了。一句话总结一下,volatile到底有什么用。它的作用就是叫编译器不要偷懒,去内存中去取值

 


 

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lucas_zgp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值