這是 C 語言面試筆試的必考經典:字元陣列與字元指標初始化字串時,記憶體佈局與可修改性的本質區別。看懂這道題,就理解了 C 語言字串存儲的核心機制。
char s[10] = "mysohu";
s[0] = 0; // 或 s[0] = '\0'
printf("%s\n", s);
輸出: (空行) — 字串被截斷為空字串

char *s = "mysohu";
s[0] = 0; // 嘗試修改首字元
printf("%s\n", s);
輸出: 運行時崩潰 (Segmentation Fault / Access Violation)

| 特性 | char s[10] = "mysohu" | char *s = "mysohu" |
|---|---|---|
| 儲存位置 | 棧 (Stack) 或數據段 (全域/靜態) | 指標在棧,字串常量在唯讀數據段 (.rodata) |
| 記憶體權限 | 可讀寫 | 字串區域唯讀 |
| 初始化過程 | 編譯器生成代碼將常量逐字元複製到陣列 | 指標直接指向常量區地址,無複製 |
| 修改合法性 | 合法,修改陣列內容 | 非法,嘗試寫入唯讀區 → 硬體異常 |
| sizeof(s) | 10 (陣列大小) | 4/8 (指標大小) |
程式一:棧區 +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ | 'm' | 'y' | 's' | 'o' | 'h' | 'u' | '\0' | ? | ? | ? | +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9] ↑ 修改為 0 → 字串結束 程式二: 棧區: 唯讀數據區: +--------+ +--------+--------+--------+--------+--------+--------+--------+ | s ──────────→ | 'm' | 'y' | 's' | 'o' | 'h' | 'u' | '\0' | +--------+ +--------+--------+--------+--------+--------+--------+--------+ 指標 唯讀!寫入觸發保護錯誤
char s[] = "..."; 或動態分配 malloc/strdupconst char *s = "..."; — 編譯器會報錯防止誤修改const char *char *p1 = "hello";
char *p2 = "hello";
// p1 == p2 可能為真 (編譯器優化合併相同常量),也可能為假 — 不可依賴
char a[] = "hello";
char b[] = "hello";
// a == b 永遠為假 (不同陣列實例)
陣列 = 容器 (可寫),指標 = 地址 (指向唯讀常量區)。這道題考察的不是語法,而是記憶體模型理解。牢記:「雙引號字串常量進入 .rodata,陣列初始化會複製,指標初始化只取址。」