C++中的volatile关键字

    C++苦字符串格式化很久了,终于在C++20标准中提供了std::format方法,于是就在makefile里面加上了-std=c++20的flag,编译其它地方都没问题,但是报了一个error,使用到的一个三方库里面有个头文件报increment of object of volatile-qualified type 'volatile int' is deprecated , 于是仔细研究了一下这个volatile关键字。

    volatile作为关键字的定义很明确,volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。但是我们怎么知道编译器什么时候会去假设这个变量的值呢?于是用godbot做了一些简单的实验,选择的是我自己使用的编译器x86-64 clang 15.0.0

        首先看下面这段简单的code

int num = 10;
int square() {
    int b = num;
    int a = num;
    return b * a;
}

      编译后的汇编代码如下:

square():                             # @square()
        push    rbp
        mov     rbp, rsp
        mov     eax, dword ptr [rip + num]
        mov     dword ptr [rbp - 4], eax
        mov     eax, dword ptr [rip + num]
        mov     dword ptr [rbp - 8], eax
        mov     eax, dword ptr [rbp - 4]
        imul    eax, dword ptr [rbp - 8]
        pop     rbp
        ret
num:
        .long   10                              # 0xa

    这是完全没有经过优化,首先把num对应的内存中的内容move到eax寄存器中,然后把寄存器内容move到b对应的内存中,对a也重复上面的过程,最后把b对应的内存中的内容移动到寄存器,然后用寄存器中的内容和a对应的内存中的内容做乘法。

    打开O3编译优化之后的汇编代码如下:

square():                             # @square()
        mov     eax, dword ptr [rip + num]
        imul    eax, eax
        ret
num:
        .long   10                              # 0xa

    直接把num对应的内存中的内容move到寄存器,然后把寄存器里面的内容相乘,编译器假设了变量a和b从num对应的内存中取出来的值是一样的,从而省略了中间的b = num和a = num两条C语句。

    修改一下code,在num的定义前面加上volatile之后的汇编代码如下

square():                             # @square()
        mov     eax, dword ptr [rip + num]
        imul    eax, dword ptr [rip + num]
        ret
num:
        .long   10                              # 0xa

    区别不大,就是最后乘的时候用的是寄存器中的值和内存中的值来乘,而不是没有volatile的时候寄存器和寄存器相乘,这样能保证乘的是最新的值,与未优化的两条C语句等价。

    看到这里我们应该明白,想要编译器对非volatile的变量做假设优化并不是很容易,需要这个变量已经在寄存器里面了,并且很快又会被用到,大多数程序很难满足这个要求,除非故意在一段code里面等待外部来改变这个变量。

    回头再去看我的项目里面报错的那个第三方头文件,那个变量在所有使用的地方都不可能做假设优化,也就是可以很放心的把volatile关键字删掉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值