volatile关键字

volatile关键字用于阻止编译器进行相关优化。编译时如果启用了编译选项,编译器会根据其自身的逻辑判断,优化代码,包括增减语句、调整语句顺序等,而这在很多特定的情况下是不被接受的。比如,读取GPIO端口值或者寄存器值,一般要求读取的值就是GPIO端口或者寄存器内当前的值。如果这些读取的语句不幸被编译器优化了,那么读取的值就有可能是一个过期的值,而不是当前状态下的真正的值。另一个比较常见的应用就是资源引用计数器,该计数器通常就被定义为一个使用了volatile关键字限定的整数,以保证每次读取的该整数的值都是最新的值。

 

考虑如下代码:


#include <stdio.h>

int main(int argc, char** argv) {
    volatile int i = 10;

    asm ("movl $20, %0;"
            :
            : "m"(i)
            );

    printf("i: %i/n", i);

    return 0;
}

 

假定该段代码存放在文件test.c中,使用如下命令编译该文件:

 

gcc -O -o test test.c

 

这里选项-O用于打开gcc优化功能。编译完成之后,运行命令./test,输出结果为

 

i: 20

 

这符合我们的期望,这表明main函数中的内嵌汇编语句生效了。而如果我们把main函数中i申明语句中的volatile语句删除,重复上述编译、运行动作之后,输出的结果则为:


i: 10

 

至此,volatile的作用体现出来了。它可以阻止一切与其有关的优化,即便编译器打开了编译选项。值得一提的是这里的内嵌汇编,它的作用是向编译器隐瞒i变量被修改的事实(内嵌汇编语句修改了i的值),从而使得在编译器打开优化选项的时候,会尝试对那些没有volatile语句限定的变量及其相关语句进行优化。此外,内嵌汇编中i放在输入操作数部分而没有放在输出操作数部分也是出于这一目的。倘若放在输出部分,编译器便会识破我们的伎俩,知道我们随后修改了i的值,进而会规避此处的优化,此时两种情况下的输出值都将一样。

 

另外volatitle和可以用来阻止编译器对内嵌汇编的优化,仅需在asm和左括号之间插上关键字volatile即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值