C 語言初學者常混淆字符 '0'、空字符 '\0' 和整數 0。本文從數值表示、內存佈局、字符串函數實現原理三個維度徹底釐清,並解析 strlen/strcpy 如何正確處理包含字符 '0' 的字符串。
| 表示形式 | 含義 | 十進制值 | 十六進制值 | 內存佔用 |
|---|---|---|---|---|
'0' | 字符『零』 | 48 | 0x30 | 1 byte (char) |
'\0' | 空字符 (Null terminator) | 0 | 0x00 | 1 byte (char) |
0 | 整數零 | 0 | 0x00 | 2/4/8 byte (int/long) |
'0'(48) ≠'\0'(0) = 整數0(0)。字符'0'是可打印字符,'\0'是字符串結束標記,兩者本質不同。
size_t strlen(const char *s) {
size_t len = 0;
while (s[len] != '\0') { // 檢測值為 0 的字節
len++;
}
return len;
}
"003.4050"
內存佈局 (十六進制):
索引: 0 1 2 3 4 5 6 7 8
字符: '0' '0' '3' '.' '4' '0' '5' '0' '\0'
數值: 30 30 33 2E 34 30 35 30 00
↑ ↑
首字符 結束符 (值 0)
strlen 從索引 0 遍歷,遇到索引 8 的 0x00 停止,返回 8'0' (0x30) 不等於 0x00,不會被誤判為結束strcpy 同理:逐字節拷貝直到拷貝 0x00 為止| 誤區代碼 | 問題 | 正確理解 |
|---|---|---|
if (str[i] == 0) | 混用整數 0 與字符 | 應寫 if (str[i] == '\0') 或 if (!str[i]),語義明確 |
memset(buf, '0', n) | 用字符 '0' 填充 | 填充的是 0x30,非 0x00;清零應用 memset(buf, 0, n) |
char c = 0; | 隱式轉換 | 合法,c 值為 0x00 (即 '\0'),但可讀性差 |
printf("%s", "003.4050") 輸出長度 8 | 以為 '0' 會截斷 | 只遇 '\0' 截斷,'0' 只是普通字符 |
char data[] = {'H', 'e', 'l', '\0', 'l', 'o', '\0'}; // 含嵌入 '\0'
printf("%s", data); // 輸出 "He" (遇第一個 \0 停止)
printf("%zu", strlen(data)); // 返回 3
// 處理二進制數據必須用長度顯式傳遞
void process_binary(const char *buf, size_t len) { ... }
這是為什麼網絡協議、文件格式解析不能用 char* + strlen,必須攜帶長度的原因。
'\0':while (*p != '\0') 或 while (*p)0 或 NULL:memset(ptr, 0, size)、ptr = NULL'0':無需轉義,ASCII 碼 48 固定uint8_t* + size_t:語義區分,避免誤用字符串函數'0' (0x30) 是字符,'\0' (0x00) 是控制字符,整數 0 (0x00) 是數值。字符串函數專門識別值為 0x00 的字節作為結束標記,與字符 '0' (0x30) 毫無關係。理解數值表示本質,是避免 C 字符串處理 Bug 的基石。