1. 程式人生 > >c語言volatile實戰分析

c語言volatile實戰分析

 寫在前面   

一直有這樣的一個概念,volatile修飾的變數,程式在讀取該值的時候,不是在暫存器中讀取,而是從變數所在的記憶體中讀取。 下面寫個程式測試一下

#include <stdio.h>

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,忽略入棧這些過程

可以看到這樣一句話  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

優化後再看,發現出現了一開始討論的問題,程式在讀取某些變數值的時候,直接讀取之前儲存在暫存器中的值

3,使用volatile修飾,同時進行優化操作

使用volatile對變數進行修飾

#include <stdio.h>

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

這裡可以看到,每次操作變數b的時候,都是  ldr r4, .L3  ldr rx, [r4, #0] 保證每次都是從變數所在的地址取值

4,結論

通過上面3個實驗,可以確認volatile可以保證程式在執行過程中,對變數的取值是從變數所在的地址而不是暫存器