--- tags: C --- # Programming Languages C - volatile slide: https://hackmd.io/@SquirrelPanda/rkaknIkXO {%hackmd ryr9Ug6sd %} --- ## 說明 ::: info volatile 是其中一種修飾符號, 代表著固定該變數的記憶體位置, 與 static 不同的是, 將用來告訴最佳化編譯器不要對使用到該變數的部分進行優化. ::: 一般編譯器在進行優化時會做到簡化程式碼、攤開程式碼等等方式, 但畢竟優化的規則也是人寫的, 某些情況下反而會因優化造成問題, 舉例來說就像 [wikipedia](https://en.wikipedia.org/wiki/Volatile_(computer_programming)) 所舉的例子: - 首先我們宣告一個 static int 的變數 foo, 此變數會在 bar function 以外都沒有實作任何賦值的動作, 只會在硬體相關 Register 行為時改變. ```c= static int foo; void bar(void) { foo = 0; while (foo != 255) ; } ``` - 經最佳編譯器處理後, 會被優化成這樣: ```c= void bar_optimized(void) { foo = 0; while (true) ; } ``` - 我們可以發現到, 最佳化編譯器因為沒有看到任何代碼修改 foo 的值而假設他永遠是 0, 進而替換成 while(true), 使得原本的判斷是改變. 因此, 我們需要將原式改成以下: ```c= static volatile int foo; void bar (void) { foo = 0; while (foo != 255) ; } ``` 而針對 volatile 可能使用的地方, 在 ISO/IEC 9899:1999(E) -- Programming Languages -- C (p121) 也有提到 : ![](https://i.imgur.com/y542BTb.png) :::info 因此當我們在處理與硬體相關的多執行序、中斷機制等, 需要避免最佳化或記憶體重新排列造成問題時就會用到. ::: 另外需要注意的是, 針對加上了 volatile 的變數, 在使用上也要注意, 舉例來說: - 這是一個計算平方的 function, 輸入的參數我們加上了 volatile. ```c= int square(volatile int *ptr) { int a,b; a = *ptr; b = *ptr; return a * b; } ``` - 然而, 因為 *ptr 隨時有可能會被改變, 有機會造成 $a \neq b$ 的狀況, 這樣就不是平方了, 因此我們應該先把值接出來, 修改如下: ```c= int square(volatile int *ptr) { int a; a = *ptr; return a * a; } ``` ## 結語 對於會直接操控 register 的 FW 來說, volatile 一定要會用的部分, 有關最佳化的問題也是會常遇到的狀況, 瞭解而不誤用十分重要. ## 其他 ### ARM CMSIS-5.3.0 - CMSIS是ARM所提供的介面, 裡面就會大量使用到 volatile, 可查看下面定義: <core_cm0.h> ```c=151 /* IO definitions (access restrictions to peripheral registers) */ /** \defgroup CMSIS_glob_defs CMSIS Global Defines <strong>IO Type Qualifiers</strong> are used \li to specify the access to peripheral variables. \li for automatic generation of peripheral register debug information. */ #ifdef __cplusplus #define __I volatile /*!< Defines 'read only' permissions */ #else #define __I volatile const /*!< Defines 'read only' permissions */ #endif #define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */ /* following defines should be used for structure members */ #define __IM volatile const /*! Defines 'read only' structure member permissions */ #define __OM volatile /*! Defines 'write only' structure member permissions */ #define __IOM volatile /*! Defines 'read / write' structure member permissions */ ``` ## 參考資料 - [ISO/IEC 9899 - Programming languages - C](http://www.open-std.org/jtc1/sc22/wg14/www/standards.html) - [wikipedia - volatile (computer programming)](https://en.wikipedia.org/wiki/Volatile_(computer_programming)) - [C語言中的volatile用法](https://www.itread01.com/content/1541733250.html)