volatile 是類型修飾符,告訴編譯器:「該變量可能被不可預知的因素(硬件、中斷、其他線程)修改,請禁用優化,每次直接從內存讀取」。
能。例:只讀狀態寄存器。
volatile:硬件可隨時修改,編譯器不可優化const:程序不應嘗試修改它const volatile uint32_t *STATUS_REG = (uint32_t*)0x40000000;
能。例:中斷中修改的緩衝區指針。
volatile char *buffer_ptr; // ISR 可能修改指針指向
// 或
char *volatile buffer_ptr; // 指針本身可能被 ISR 修改
int square(volatile int *ptr) {
return *ptr * *ptr; // 錯誤!
}
問題:編譯器會展開為兩次讀取:
int a = *ptr;
int b = *ptr; // 兩次讀取中間,硬件/中斷可能修改 *ptr
return a * b; // 結果可能不是平方!
正確寫法:
long square(volatile int *ptr) {
int val = *ptr; // 只讀取一次
return val * val;
}
#include <stdio.h>
void main() {
int i = 10;
int a = i;
printf("i = %d\n", a);
// 內聯匯編直接修改內存,繞過編譯器知曉
__asm {
mov dword ptr [ebp-4], 20h // 將 i 改為 32
}
int b = i;
printf("i = %d\n", b);
}
| 模式 | 未加 volatile | 加上 volatile |
|---|---|---|
| Debug | 10, 32 | 10, 32 |
| Release | 10, 10 (優化掉第二次讀取) | 10, 32 (強制重讀) |
⚠ 關鍵誤區:volatile 不保證原子性,不提供內存屏障,不能替代互斥鎖/原子操作。
std::atomic 或鎖atomic,而非單純 volatile#define REG (*(volatile uint32_t*)0xXXXXXXXX) 是標準寫法