const 用法靈活、語義豐富,是新手最易困惑的關鍵字之一。建議配合閱讀《C++基礎 詳細介紹const的用法》與《C++初學者 const使用詳解》。本文從底層記憶體角度剖析 const 的真實行為。
const int a = 2; 宣告 a 為常變數,意指不能透過 a 這個符號直接修改其值。但實際上,記憶體位置的內容仍可被間接修改:
const int a = 3;
int* p = (int*)&a; // 強制轉型移除 const
*p = 100;
printf("%d", a); // 輸出 100(視編譯器最佳化而定)
編譯器可能將 a 優化為立即數嵌入指令碼,導致實際記憶體修改不影響輸出。const 非絕對不可變,而是編譯器層面的寫入保護。
int arr[10] = {0};
const int* ptr = arr; // ptr 可變,指向的內容不可透過 ptr 修改
// *(ptr+1) = 2; // 編譯錯誤
ptr = other_arr; // 合法:改變指向
同樣可透過非 const 別名間接修改:
int arr[10] = {0};
const int* ptr = arr;
int* ptr1 = (int*)ptr; // 移除 const
ptr1[0] = 1; // 合法,arr[0] 變為 1
指標本身不可變更指向,宣告時必須初始化:
int a = 2;
int* const p = &a; // p 永遠指向 a
// p = &other; // 編譯錯誤
同樣可透過二級指標間接修改:
int* const p;
int** p1 = (int**)&p;
*p1 = &a; // 合法,p 現在指向 a
const int* const p = &a; // 指向不可變、指向內容不可變(雙重保護)
綜合上述兩種語義,無需贅述。
const int* p → p 是指標 → 指向 int → const(內容唯讀);int* const p → p 是 const 指標 → 指向 int。const 修飾右側實體(型別或指標本身),靠位置區分語義。理解 const 的編譯器語義與底層實作差異,能避免大量難以除錯的邏輯錯誤。