C-关键字之volatile

在上个文章里提到了volatile关键字,这里进行一下总结。里面有网上查到的,也有我使用STM32单片机时关于volatile的心得。

Volatile总是和优化有关,编译器有一种技术叫数据流分析,分析程序中变量在哪里赋值,在哪里使用。但这时有些优化并不为程序需要,这时可以用volatile禁止做这些优化。Volatile的字面含义是易变的。

它有以下作用:

1、不会在两个操作之间把volatile变量缓存到寄存器中。在多任务、中断、jmp下,变量可能被其他程序改变,编译器无法自己知道,volatile就是告诉编译器这种情况。

2、不做常量合并等优化。比如:

            volatile int i =1; 
            if (i > 0) ... 
if的条件不会当作无条件真。 如果i前面没有volatile的话,那if的条件就会被不加判断就认为是真值;现在有了volatile,软件会从内存中读出i的值,然后再来比较判断。

3、volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没有用到,那编译器常常省略这个操作。

应用举例1:


我用的VS2010,在debug模式下。两段代码输出都是一样的,都是打印10,32。因为debug模式没有对代码进行优化。所以volatile关键字的作用看不出来。

在release模式下,编译器对代码进行了优化(左边的代码中_asm里面的就被优化掉了)。

这样左边的代码输出是10,10;而右边的代码输出是10,32。

注:bsp是栈顶指针,指向下一个压栈时存放数据的地址。这样bsp-4就是i在栈里的地址。

应用举例2:往某一个地址发送两次数据

这样就会造成第一条指令丢失,如果用了volatile,就不会被允许优化。

Volatile的应用场景:

1、中断服务程序中,修改的其他程序检测的变量,需要加volatile

2、多任务环境下,各任务间共享的标志应加volatile

3、存储器映射的硬件寄存器通常也要用volatile说明,因为每次对它的读写都可能有不同的含义。(这就是STM32的SRAM与外设之间的映射)。

         Volatile与STM32:

         大多数 C编译器不支持位段操作。如在使用不同的地址时,C编译器不会认为访问的是同一存储器区域,而且他们也不知道对位段别名的访问只会操作该存储位置的最低位。

         比如:0x40000000与0x4200 0000访问的都是0x4000 0000这一区域,而C编译器会认为它们是两个地址。

在使用位段特性时,变量需被声明为volatileC编译器不知道同一个数据可以在不同的地址中访问。因此volatile属性可以确保每次在操作一个变量时,访问的是存储器位置而不是处理器内部的本地数据复制。


猜你喜欢

转载自blog.csdn.net/fxltsbl007/article/details/80475212