2007-12-23

關於C語言中的volatile修識字

詳細說明請參考網址→http://www.programmersheaven.com/articles/pathak/article1.htm

之前暑假在樓下學SoC程式設計時就遇過volatile這關鍵字,當時授課的助教只說他也不清楚這意思,要大家照抄就是了。現在實驗室也開始玩SoC發展平台,自然的有一部分就是要寫一些程式控制周邊硬體,以上都是廢話XD

由於ARM都是採用memory-map方式存取周邊裝置,因此要對周邊裝置溝通只要把資料丟進記憶體或從記憶體讀取資料就可以了,但這時聰明的編譯器反而可能變成壞了大了事的老鼠屎,原來是幫程式碼最佳化的功能反而成了困擾,請參考底下程式碼:

*ptr = 0;
while(*ptr){
*ptr = 4 ;
*ptr = 0 ;
}

這段內容很可能會被聰明的編譯器給最佳化成了下面的樣子:
*ptr = 0
while(0) {
}

從軟體角度來說,這是編譯器幫不聰明的Programmer化簡了多餘的冗碼;在硬體角度來看,可能就不見得是好事了,如果Programmer原本就是希望*ptr指到的位址訊號一直由0與4交互替換,那這時編譯器就幫倒忙了!
若要避免這窘境發生,可以在宣告*ptr變數時,加上volatile修識字讓每次的存取都乖乖的照作,並且是到記憶體進行讀取,而不使用暫存器。

1 則留言:

匿名 提到...

感謝你對volatile的解釋,讓我了解為什麼要使用volatile。
我想簡單的說,就是某些變數在改變時,那些改變並不會讓compiler知道,因此在存取時就會存取目前在register的尚未改變的數值,而沒有實際去memory去取值,造成程式錯誤。
但加了volatile就會強迫每次的存取都是從memory不從register,並且也跟compiler對此變數做優化的行為,理由如同你的例子:)。