C语言volatile用法/Keil编译器优化/delay被编译器优化

1、volatile简要说明

volatile英文意思为易变的、易挥发的,在声明变量时加入这个关键字,**意思就是告诉编译器这个变量随时能被外部修改,不要对此变量进行优化,代码中引用此变量必须访问内存中实际变量。**有的小伙伴可能看到这里会很懵,CPU访问变量不就是访问内存中的实际变量吗,并不是这样的,CPU内部还有寄存器,CPU读写寄存器的速度是远大于读写内存的速度,为了提高程序的执行速度,编译器会优化代码,把实际的变量存放到寄存器中,通过读写寄存器来访问该变量。

2、引用keil官方的编译器用户指南例程说明

下图有两个函数,左边跟右边函数的区别就是右边函数声明变量buffer_full时加入了volatile关键字。
在这里插入图片描述
使用-O2选项来编译上图代码,反汇编后得到下图
在这里插入图片描述
分析:左边编译器对buffer_full变量进行了优化,在进入L1.12循环前,先把buffer_full变量的值存放到r1寄存器中,进入while循环后直接使用r1寄存器中的值,并没有访问实际的buffer_full变量,如果buffer_full变量在外部被修改了,程序就会得到意想不到的结果。右边声明变量buffer_full时加入了volatile关键字,每次进入L1.8循环时都会读取内存中buffer_full变量的值并存放到r2寄存器,用r2的值来判断是否继续执行循环,即使某一时刻buffer_full变量在外部被修改了,程序仍然可以达到预期的效果。

3、实验验证

使用GD32单片机,实验方法:执行delay函数(count相同)前后,控制GPIO的电平变化,用示波器抓取波形,测量出函数运行的时间。下面两个函数的区别是下面函数声明变量us 时加入了volatile关键字。

void my_delay(unsigned int count)
{
    for(int i = 0; i < count; i++)
    {
        uchar us = 12;   
        while (us--) ;
    }
}

测试结果如下:
-O0优化下,测得是68us
-O2优化下,测的是47.6us

void my_delay(unsigned int count)
{
    for(int i = 0; i < count; i++)
    {
        volatile uchar us = 12;    
        while (us--) ;
    }
}

测试结果如下:
-O2优化下,测的是86us
实验分析:
同样使用-O2优化等级,加了volatile关键字的delay函数,执行速度变慢了。
加了volatile关键字的delay函数,使用-O2优化等级,执行速度比不加volatile关键字的delay函数(使用-O0优化)还慢,说明了使用-O0优化编译器仍然会作一定优化。

补充实验,声明变量count时也加入了volatile关键字,

void my_delay(volatile unsigned int count);
void my_delay(volatile unsigned int count)
{
    for(int i = 0; i < count; i++)
    {
        volatile uchar us = 12;
        while (us--) ;
    }
}

测试结果如下:
-O2优化下,测的是107.6us
实验分析:delay函数执行的更慢了
结论:为了避免优化对delay执行速度的影响,需要注意volatile关键字的使用,否则程序可能会在开优化后会产生意想不到的结果。

4、使用volatile的场景

  • 访问内存映射的外设
  • 多线程共享的全局变量
  • 在中断例程中访问的全局变量
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值