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可以保證程式在執行過程中,對變數的取值是從變數所在的地址而不是暫存器