char arr[常量表達式]; // 未初始化,內容不定
char arr[SIZE] = {'a','b','c'}; // 列表初始化
char arr[] = "Hello"; // 字符串字面量初始化(含隱式 \0)
關鍵點:數組長度必須為編譯期常量(C99 允許 VLA,但不推薦用於字符串)。
| 形式 | 代碼示例 | 內存佈局 | 說明 |
|---|---|---|---|
| 全量指定 | char a[5] = {'h','e','l','l','o'}; | 5 字節,無 \0 | 非字符串,不可用 %s/strlen |
| 部分初始化 | char a[5] = {'h','e'}; | h e \0 \0 \0 | 剩餘自動補 0 |
| 字符串字面量 | char a[] = "hello"; | h e l l o \0 | 編譯器自動添加 \0,長度含終止符 |
| 字符串指定長度 | char a[10] = "hello"; | h e l l o \0 \0 \0 \0 | 剩餘補 0,長度固定 10 |
// 字符串常量(唯讀數據段 .rodata)
"Hello" // 內存:H e l l o \0
// 字符數組(棧/數據段,可修改)
char arr1[] = {'H','e','l','l','o'}; // 無 \0
char arr2[] = "Hello"; // 含 \0,編譯器複製常量到數組
char *p = "Hello"; // 指向常量區,p[0]='h' 導致崩潰!
核心區別:字符串常量自帶 \0 且通常置於唯讀段;字符數組是可修改的容器,初始化時可選擇是否複製 \0。
printf("Hello\0World"); // 輸出 "Hello" —— 遇到 \0 即停止
char s[] = "Hello\0World";
printf("%s", s); // 同理,只打印 "Hello"
printf("%zu", strlen(s)); // 返回 5,而非 11
char str1[15] = {"Hello"}; // 帶花括號
char str2[15] = "Hello"; // 無花括號(常用)
char str3[] = "Hello"; // 自動推導長度(含 \0,長度 6)
| 函數 | 格式符 | 行為 | 注意事項 |
|---|---|---|---|
scanf | %s | 跳過前導空白,讀取至下一空白(空格/換行/制表/\0) | 極易溢出,無長度限制。實戰用 %19s (長度-1) |
printf | %s | 從地址輸出至遇到 \0 | 無 \0 導致越界讀取,極度危險 |
char buf[20];
scanf("%19s", buf); // C99: 限制寬度,預留 1 字節給 \0
// 或更安全:
fgets(buf, sizeof(buf), stdin); // 讀整行含 \n,需手動去除
char s[] = "Hello\0World";
printf("%zu\n", strlen(s)); // 5 —— 僅計算首個 \0 前的字符數
printf("%zu\n", sizeof(s)); // 12 —— 數組總字節數(含結尾 \0 和後續字符)
strlen 遍歷查找 \0,時間複雜度 O(n);sizeof 編譯期常量,O(1)。
<string.h>)| 函數 | 原型 | 作用 | 關鍵前提 |
|---|---|---|---|
strlen | size_t strlen(const char *s) | 有效長度(不含 \0) | s 必須以 \0 結尾 |
strcpy | char *strcpy(char *dest, const char *src) | 複製含 \0 | dest 空間必須 ≥ src 長度+1,否則溢出 |
strncpy | char *strncpy(char *dest, const char *src, size_t n) | 複製至多 n 字符 | 若 src 短於 n,補 \0;否則 不自動添加 \0 |
strcat | char *strcat(char *dest, const char *src) | 追加 src 到 dest 末尾 | dest 必須有足夠空間且以 \0 結尾 |
strcmp | int strcmp(const char *s1, const char *s2) | 字典序比較 | 返回 <0, =0, >0;逐字節比較,遇異即止 |
scanf("%s")/strcpy:使用寬度限制或安全版本(strncpy_s、strcpy_s C11 可選)。char *p = "abc"; p[0]='x'; // UB,改用 char p[] = "abc";。memcpy/memcmp 並顯式傳長度。掌握字符數組與字符串的內存佈局、\0 約定、輸入輸出邊界,是寫出健壯 C 代碼的基本功。