初學者常見困惑:char name[] = "abcdef"; 可作為引數傳入 reverse() 反轉成功,但改成 char* name = "abcdef"; 卻導致執行期錯誤(存取違規)。
| 宣告方式 | 儲存區域 | 可修改性 | 存留期 |
|---|---|---|---|
char name[] = "abcdef"; | 堆疊 | 可讀寫 | 函式結束釋放 |
char* name = "abcdef"; | 唯讀資料段 | 唯讀 | 程式結束釋放 |
void reverse(char* s)
{
char *p = s, *q = s + strlen(s) - 1, temp;
while (p < q) { temp = *p; *p = *q; *q = temp; p++; q--; }
}
p、q 分別指向字串首尾。*p = *q 嘗試寫入記憶體——若 s 指向唯讀段,即觸發 Segmentation Fault。char name[] = "abcdef"; // 編譯器在堆疊配置 7 bytes 並複製字面值
reverse(name); // 安全
char* name = malloc(7);
strcpy(name, "abcdef"); // 複製到可寫堆積記憶體
reverse(name);
free(name);
char* name = "abcdef"; // 指標指向 .rodata 段
reverse(name); // Crash!
sizeof(name) 對陣列回傳整個大小,對指標回傳指標大小(4/8 bytes)。const char*,編譯器將協助攔截錯誤用法。const 資料是否真正被編譯器放入 Flash 唯讀區。深入理解 C 語言陣列轉指標規則 與 字串常量儲存類別,是避免此類 Bug 的關鍵。