字符指針 char *p = "hello" 與字符數組 char a[] = "hello" 外觀相似,本質天壤之別。本文從存儲、賦值、修改、傳參四個維度深度對比。
| 特性 | 字符指針 char *p | 字符數組 char a[] |
|---|---|---|
| 本質 | 指針變量,存地址 | 數組對象,存內容 |
| 字符串存儲 | 只讀數據區(字面量) | 棧上(可修改) |
| 初始化後賦值 | p = "world" ✅ | a = "world" ❌ 數組名非左值 |
| 修改字符內容 | p[0]='H' ❌ 段錯誤 | a[0]='H' ✅ |
| sizeof 結果 | 指針大小(4/8 字節) | 數組總長度(含 \0) |
| 作為參數傳遞 | 傳指針值 | 退化為指針傳遞 |
// ❌ 危險:指向隨機地址
char *name;
scanf("%s", name); // 未定義行為
// ✅ 修正:用數組
char name[20];
scanf("%s", name);
// ✅ 修正:分配內存
char *name = malloc(20);
scanf("%s", name);
free(name);
// ❌ 運行時崩潰 char *p = "hello"; p[0] = 'H'; // 段錯誤 // ✅ 正確:用數組 char a[] = "hello"; a[0] = 'H'; // 合法 // ✅ 正確:只讀指針 const char *p = "hello"; // p[0] = 'H'; // 編譯期報錯
字符指針: 字符數組:
棧區:p ──────┐ 棧區:a[0]='h'
│ a[1]='e'
只讀區:"hello"←┘ a[2]='l'
a[3]='l'
a[4]='o'
a[5]='\0'
// 輸入參數:只讀
void print_str(const char *str); // 接受指針或數組
// 輸出參數:需寫入
void get_str(char *buf, int size); // 必須傳可寫緩衝區(數組或 malloc)
// 返回字符串:靜態/動態分配
const char *get_literal() { return "fixed"; } // 字面量安全
char *get_dynamic() { return malloc(n); } // 調用者須 free
const:const char *p = "..."mallocconst char *free