volatile 告訴編譯器:該變量可能在程序不可控處被修改(硬件、中斷、其他線程),每次讀寫必須訪問內存,不能用寄存器緩存。
const int *p 傳遞「只讀意圖」只讀硬件寄存器:程序不應修改(const),但硬件會自動更新(volatile)。
const volatile uint32_t *STATUS_REG = (uint32_t *)0x40000000; // 讀取:uint32_t val = *STATUS_REG; // 每次必讀內存 // 寫入:編譯報錯,符合語義
volatile int *p1; // 指向 volatile int 的指針:*p1 讀寫不優化 int *volatile p2; // volatile 指針:p2 本身不優化(地址可能變) volatile int *volatile p3; // 兩者皆 volatile
嵌入式常見:中斷修改指向緩衝區的指針 → int *volatile buf_ptr。
// 錯誤版本:編譯器可能優化為讀取兩次 *ptr,若 ptr 指向硬件寄存器,兩次值不同
int square(volatile int *ptr) {
return *ptr * *ptr;
}
// 正確版本:先存入局部變量
int square(volatile int *ptr) {
int val = *ptr;
return val * val;
}
原理:volatile 只保證單次訪問不優化,不保證表達式內多次訪問一致性。
| 關鍵字 | 核心語義 | 典型用途 | 編譯器行為 |
|---|---|---|---|
| volatile | 值可能意外改變 | 硬件寄存器、ISR共享變量、多線程標誌 | 禁用寄存器緩存,每次強制內存訪問 |
| const | 只讀語義 | 函數參數、配置常量、只讀硬件寄存器 | 編譯期禁止寫入,優化只讀傳播 |
| const volatile | 只讀且可能外部變 | 只讀狀態寄存器 | 禁止寫入 + 強制每次讀內存 |
reg_def.h 統一定義寄存器映射,統一加 volatile_Atomic / C++ std::atomic,volatile 僅作標誌位volatile 是嵌入式 C 與應用層 C 的分水嶺。徹底理解「編譯器優化 vs 硬件現實」的衝突,正確使用 volatile/const/const volatile,是寫出可靠固件的關鍵。