const 告訴編譯器:「這個變數初始化後不可修改」。它不是常數(compile-time constant),而是「唯讀變數」(read-only variable),編譯器會在編譯期攔截寫入行為。
const int MAX = 100; // 唯讀整數 int const MAX = 100; // 相同,慣用前者 // MAX = 200; // 編譯錯誤:assignment of read-only variable
int n = 10;
int arr1[n]; // C99 VLA,非標準 C++,某些編譯器不支援
const int m = 10;
int arr2[m]; // 標準 C:const 整數可作為陣列大小(視編譯器而定,C99 後較穩)
// 建議:#define SIZE 10 或 enum { SIZE = 10 } 最可攜
核心口訣:**「const 修飾誰,誰就不可變」** —— 看 const 最近的標識符。
| 宣告 | 語意 | 指標可改? | 指向值可改? |
|---|---|---|---|
const int *p;int const *p; | 指向 常數整數 的指標 | ✅ p = &other | ❌ *p = 20 |
int *const p; | 指向整數的 常數指標 | ❌ p = &other | ✅ *p = 20 |
const int *const p; | 指向常數整數的常數指標 | ❌ | ❌ |
int *const p → p is a **const pointer** to intconst int *p → p is a pointer to **const int**const int *const p → p is a **const pointer** to **const int**void printStruct(const BigStruct *p) {
// 保證不會修改結構體內容,呼叫端放心傳遞
printf("%d\n", p->id);
}
const char *getErrorMsg(int code) {
static const char *msgs[] = {"OK", "FAIL"};
return msgs[code]; // 呼叫端無法修改字串常值
}
const char *str = "hello"; // 正確:字串常值存放在唯讀區 // str[0] = 'H'; // 執行期崩潰(段錯誤) char *bad = "hello"; // 危險:C 標準允許但棄用,C++ 禁止
volatile const int *port = (volatile const int *)0x1000; // volatile:告訴編譯器「值可能被硬體隨時改變,不要優化讀取」 // const:程式碼不應主動寫入此位址 // 適用於唯讀硬體暫存器(如狀態暫存器)
// 變數 const int a = 10; // a 唯讀 // 指標 const int *p1; // *p1 唯讀(指向常數) int *const p2 = &a; // p2 唯讀(常數指標),需初始化 const int *const p3 = &a; // 兩者皆唯讀 // 函式 void f(const int *p); // 不修改 *p void f(int *const p); // 不修改 p(較少見) void f(const int *const p); // 兩者不修改 // 字串 const char *s = "text"; // 標準寫法
善用 const 能讓介面契約更清晰、編譯器協助找出邏輯錯誤、優化器產生更好機器碼。記住核心原則:**「越接近 const 的標識符受保護」**,由右往左讀聲音即可秒懂所有宣告。