| 特性 | 'C' (字符常量) | "C" (字符串常量) |
|---|---|---|
| 類型 | int (C89/C99) / char (C++) | const char[2] (退化為 const char*) |
| 大小 | sizeof('C') == sizeof(int) (通常 4) | sizeof("C") == 2 (含隱含 \0) |
| 值 | ASCII 碼 67 (可參與算術運算) | 地址 (指向只讀內存區 {'C', '\0'}) |
| 內存佈局 | 立即數,編譯期常量,不佔運行時數據段 | 只讀數據段 .rodata,地址固定,不可修改 |
| 修改後果 | 不適用 (非左值) | **未定義行為** (段錯誤/沉默破壞) |
"C" 實際內存: 0x43 0x00 ('C' + '\0')
"AB" 實際內存: 0x41 0x42 0x00
"" 實際內存: 0x00 (空字符串也佔 1 字節)
標準庫函數 (strlen, strcpy, printf("%s"), strcat) **全部依賴 \0 判斷結尾**。
// 陷阱 1: 字符串字面量去修改
char *p = "hello";
p[0] = 'H'; // UB! 段錯誤 (只讀內存)
// 正確
char arr[] = "hello"; // 棧上複製一份
arr[0] = 'H'; // OK
// 陷阱 2: sizeof 混淆
char *p = "hello";
sizeof(p); // 8 (指針大小, 64位)
sizeof("hello"); // 6 (含 \0)
// 陷阱 3: 字符 vs 字符串作函數參數
void foo(int c) { printf("%c\n", c); }
void bar(const char* s) { printf("%s\n", s); }
foo('A'); // OK, 印 'A'
foo("A"); // 警告: 指釖轉換為整數, 印亂碼
bar('A'); // 警告: 整數轉換為指釖, 崩潰
bar("A"); // OK, 印 "A"
'c',字符串用 "str",嚴禁混用;const char*,需要修改用數組 char buf[] = "...";-Wwrite-strings (GCC/Clang) 將字符串字面量類型視為 const char*,編譯期捕獲修改企圖;TCHAR/LPCTSTR,實際映射 char/wchar_t,配合 _T("str") 宏。