首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言字符與字符串本質區別深度解析:單引號vs雙引號

     編輯:關於C

C 語言中單引號表示字符,雙引號表示字符串,二者本質截然不同。誤用會導致詭異 Bug。本文通過實驗代碼、內存視圖、編譯器行為詳細對比兩者本質。

實驗 1:字符常量特性


char ch_1 = 'a';
char ch_2 = 'abcd';        // 警告:截斷
int ch_val_1 = 'abcdef';   // 錯誤:超過 4 字節
int ch_val_2 = 'abcd';     // 合法

VS2010 編譯結果

變量值(十六進制)說明
ch_10x61'a' 的 ASCII
ch_20x64取最後一字符 'd'
ch_val_20x61626364'a''b''c''d' 組合
ch_val_1('abc')0x00616263高位補 0

核心結論

  • 字符常量本質是整數,值為 ASCII 碼組合
  • 多字符常量 'abcd' 非標準,編譯器行為不一(VC 取尾,GCC 可能警告/錯誤)
  • 超過 int 寬度(4 字節)會報錯,不會自動截斷

實驗 2:字符串常量特性


char *p1 = "testchar";
char *p2 = (char*)0x74657374;  // 手造指針
char *p3 = "testchar";
char *p4 = "char";             // 子串

關鍵觀察

  • p1 == p3:編譯器合併相同字面量(唯讀段優化)
  • p1 != p4:子串不共享地址,因無長度資訊無法切片
  • 修改 *p1 = 'X' → 運行時崩潰(段錯誤),字面量在 .rodata 唯讀段
  • printf(p1) 正常:傳入首地址,遇 \0 停止

本質區別總結表

特性單引號 'a'雙引號 "a"
本質整數常量指向無名陣列的指針
大小sizeof(int)字符數+1 (含\0)
存儲區立即數/指令中.rodata 唯讀數據段
可修改N/A (非左值)不可修改 (運行時崩潰)
相同內容合併無此概念編譯器優化合併
類型int (C89) / char (C++)char* / const char*

常見陷阱與避坑


// 陷阱 1:字符 vs 字符串作參數
void foo(char c); void bar(char *s);
foo('a');   // 正確
foo("a");   // 警告:指針轉整數
bar("a");   // 正確
bar('a');   // 錯誤:整數轉指針

// 陷阱 2:字符串字面量修改
char *s = "hello";
s[0] = 'H';  // 未定義行為,通常崩潰
// 正確:
char s[] = "hello";  // 棧上陣列,可修改
s[0] = 'H';          // OK

// 陷阱 3:sizeof 差異
sizeof('a')   // 4 (int)
sizeof("a")   // 2 (含\0)

最佳實踐

  • ✅ 字符字面量用 'a',字符串用 "a"
  • ✅ 需修改字符串時,用陣列 char s[] = "..."
  • ✅ 函數參數用 const char* 接收字面量
  • ✅ 不要比較字符串指針 p1 == p2,用 strcmp
  • ✅ 理解 'abcd' 非標準,移植性差,避免使用
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved