c语言volatile实战分析

 写在前面   

一直有这样的一个概念,volatile修饰的变量,程序在读取该值的时候,不是在寄存器中读取,而是从变量所在的内存中读取。
下面写个程序测试一下

#include 

int b = 100;

int main(void)
{
    int a = b;
    int c;
    a+=3;
    b+=5;
    c = b;
    c+=7;
    printf("a = %d\n",a);
    printf("b = %d\n",b);
    printf("c = %d\n",c);
}

gcc编译流程
    1.预处理,生成预编译文件(.文件):
        gcc –E hello.c –o hello.i
    2.编译,生成汇编代码(.s文件):
        gcc –S hello.i –o hello.s
    3.汇编,生成目标文件(.o文件):
        gcc –c hello.s –o hello.o
    4.链接,生成可执行文件:
       g cc hello.o –o hello

1,不进行优化操作

这里使用 arm-linux-gcc 编译
arm-linux-gcc -E volatile.c -o volatile.i
arm-linux-gcc -S volatile.i -o volatile.S
查看volatile.S,忽略入栈这些过程

c语言volatile实战分析_第1张图片

可以看到这样一句话
 ldr r3, .L3
 ldr r3, [r3, #0]
这句话的目的就是从变量b的地址中取出b的值
这个过程中涉及到b变量的操作都是从变量地址中取出,未出现之前说的从寄存器中获取

2,进行优化操作

下面在编译的时候进行优化一下
arm-linux-gcc -E volatile.c -o volatile.i
arm-linux-gcc -O1 -S volatile.i -o volatile.S

c语言volatile实战分析_第2张图片

优化后再看,发现出现了一开始讨论的问题,程序在读取某些变量值的时候,直接读取之前保存在寄存器中的值

3,使用volatile修饰,同时进行优化操作

使用volatile对变量进行修饰

#include 

volatile int b = 100;

int main(void)
{
    int a = b;
    int c;
    a+=3;
    b+=5;
    c = b;
    c+=7;
    printf("a = %d\n",a);
    printf("b = %d\n",b);
    printf("c = %d\n",c);
}

编译的时候进行优化一下
arm-linux-gcc -E volatile.c -o volatile.i
arm-linux-gcc -O1 -S volatile.i -o volatile.S

c语言volatile实战分析_第3张图片

这里可以看到,每次操作变量b的时候,都是
 ldr r4, .L3
 ldr rx, [r4, #0]
保证每次都是从变量所在的地址取值

4,结论


通过上面3个实验,可以确认volatile可以保证程序在运行过程中,对变量的取值是从变量所在的地址而不是寄存器

 

你可能感兴趣的:(C)