1. 前言
C 語言在系統開發與嵌入式開發的現場仍然被廣泛使用。其中「char 陣列」是處理字串時最基本且重要的語法要素之一。
C 語言沒有標準的字串型別。相反地,使用字元陣列(char 陣列)來表示字串。對於初學者而言這並不直觀,因而對 char 陣列的理解常成為學習 C 語言的重大障礙。
此外,若未了解 char 陣列與 char 指標(char*)的區別,以及空字元(\0)的存在等細節規格,將會成為意外錯誤的原因。
本文聚焦於「C 語言 char 陣列」主題,從基本用法到進階技巧,並清楚說明常見錯誤的避免方法。
想要正式學習 C 語言或想複習 char 陣列的讀者,請務必看到最後。下一章將先說明 char 陣列的定義與基本機制。
2. char陣列是什麼?
在 C 語言中,「char 陣列」是用來將多個文字(char 型)一起儲存的陣列。這是處理字串時的基本結構。
char 型是什麼?
在 C 語言中,char 型是用來表示單一字元的資料型別。例如,可以這樣定義單一字元的變數。
char c = 'A';如此,'A' 這樣以 單引號 包住的單一字元,會被定義為 char 型。
char 陣列的基本語法
若要儲存多個字元,使用 char 型的陣列。可如下定義:
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};此陣列為 "Hello" 這個 5 個字元的字串加上 \0(空字元),共確保了 6 個字元的記憶體空間。
空字元('陣列的大小與注意事項
')的重要性
陣列的大小與注意事項
'在 C 語言中,使用 空字元 '\0' 來表示字串的結尾。若沒有此符號,字串操作函數 將無法正確運作,可能會產生未預期的行為。
char str[] = "Hello"; // 自動在末尾加入 '\0'如上所示,使用以 雙引號 包住的字串常量,編譯器 會自動在末尾加入 '\0'。
3. char 陣列的宣告與初始化
使用 char 陣列時,基本上要確保 必要的文字數 + 1(空字元分) 的大小。若將字串寫入大小不足的陣列,會導致 緩衝區溢出,程式可能異常終止。
靜態宣告與初始化
為了使用 char 陣列,首先需要適當的宣告與初始化。這裡將說明 C 語言中 char 陣列的基本宣告方法、初始化方式,以及動態記憶體的使用。
使用字串常值的初始化
最基本的方法是明確指定陣列大小進行宣告,並逐一字元初始化。
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};這樣一來,str 會被視為 "Hello" 的字串。重要的是,必須在末尾包含 '\0'。
指定大小並賦值字串常值
在 C 語言中,也可以使用字串常值進行簡易的初始化,如下所示。
char str[] = "Hello";在此情況下,陣列的大小會自動成為 "Hello" + '\0' 的 6 個字元。若要修改字串內容,將其宣告為 char 陣列即可安全地重新寫入。
使用動態記憶體配置(malloc)
雖然可以在指定陣列大小的同時,用字串常值初始化,但必須注意大小不足。
char str[5] = "Hello"; // ❌ 錯誤的原因(大小不足)如上所示,"Hello" 需要 5 個字元加上 1 個(’\0’)共計 6 個字元。因此,至少需要宣告為 char str[6]。
4. 字串操作
若想更靈活地處理字串,可以使用 malloc 來動態分配 char 陣列。
#include
#include
char* str = malloc(6 * sizeof(char));
strcpy(str, "Hello");此方法會動態分配記憶體,並透過指標操作字串。使用完畢後,務必使用 free(str); 釋放記憶體。
字串複製:strcpy
在 C 語言中,char 陣列進行的字串操作,通常會利用標準函式庫的函數。在這裡,我們將以具體範例,說明基本的字串操作函數及其使用方法。
字串串接:strcat
strcpy是將一個字串複製到另一個 char 陣列的函數。
#include
char src[] = "Hello";
char dest[10];
strcpy(dest, src);注意事項: dest如果沒有確保足夠的大小,就會造成緩衝區溢位。大小應確保為複製字串的長度+1(空字元)。
取得字串長度:strlen
strcat是將兩個字串結合。第 2 個引數的內容會附加到第 1 個引數的末尾。
#include
char str1[20] = "Hello";
char str2[] = " World";
strcat(str1, str2);結果,str1會變成 "Hello World"。第 1 個引數的陣列也必須有串接後整體大小能容納的餘裕。
字串比較:strcmp
strlen函數會傳回字串的長度(不含空字元的字元數)。
#include
char str[] = "Hello";
int len = strlen(str); // len = 5由於不計算空字元,不熟悉 C 語言的人需要注意。
字串搜尋:strchr 和 strstr
要比較兩個字串是否相同,可以使用strcmp。
#include
char str1[] = "Hello";
char str2[] = "World";
if (strcmp(str1, str2) == 0) {
// 相同
} else {
// 不同
}此函數在相同時傳回 0,不同時傳回字元碼的差異。
5. char 陣列與指標的差異
要搜尋特定字元或部分字串,可以使用以下函數。
#include
char str[] = "Hello World";
// 字元的搜尋
char *ptr1 = strchr(str, 'o'); // 指向第一個 'o' 的指標
// 部分字串的搜尋
char *ptr2 = strstr(str, "World"); // 指向 "World" 起始位置的指標找不到時,兩個函數都會傳回 NULL。
宣告的差異
在 C 語言中處理字串時、char 陣列與char 指標(char*)看似相似,實際上卻具有不同的性質的特性。正確理解此差異,可防止記憶體誤用與意外的錯誤。
可寫性差異
首先來看看宣告方式的差異。
char str1[] = "Hello"; // char 陣列
char *str2 = "Hello"; // char 指標str1是具有實體的陣列,在記憶體上會分配 6 位元組(”Hello” + ‘\\0’) 。另一方面,str2是指向儲存字串常值的記憶體區域的指標。
記憶體結構的差異
陣列的str1可以自由修改陣列內的字元。
str1[0] = 'h'; // OK然而,char* str2 = "Hello"; 如同以指標存取字串常值的情況下,修改其內容屬於未定義的行為。
str2[0] = 'h'; // ❌ 未定義的行為(可能發生執行時錯誤)取得大小的差異
char陣列堆疊上char指標常數區域(唯讀)堆區域(malloc 等)記憶體的處理需要注意
總結: 使用上的要點
在陣列的情況下,sizeof(str1) 會返回陣列的整體的位元組數。
char str1[] = "Hello";
printf("%lu", sizeof(str1)); // → 6(含空字元)另一方面,指標則 sizeof(str2) 會返回指標本身的大小(通常 4〜8 位元組),因此無法用於取得陣列大小的目的。
char *str2 = "Hello";
printf("%lu", sizeof(str2)); // → 8(64 位元環境)

6. 函式傳遞 char 陣列的方式
| 項目 | char配列 | char指標 |
|---|---|---|
| 內容更改 | 可能 | 原則不可(字面情況) |
| 取得尺寸 | sizeof() | strlen() |
| 重寫用途 | 適合 | 不適合(只讀) |
| 柔軟性 | 固定尺寸 | 柔軟,但需注意 |
基本範例:將 char 陣列作為參數傳遞
在 C 語言中,將陣列傳遞給函式時,會使用「指標傳遞」而非「值傳遞」。這對 char 陣列 也是相同的,傳遞給函式時會傳遞陣列的首位位址(指標)。
了解這個機制在函式間操作字串或修改內容的情況下非常重要。
修改內容的函式
#include
void printString(char str[]) {
printf("文字列: %s
", str);
}
int main() {
char greeting[] = "Hello";
printString(greeting);
return 0;
}在此範例中,printString 函式接收 char[] 型的參數,但實際上是以 char* 的形式接收。也就是說,char str[] 等同於 char *str。
陣列大小的管理
即使在函式內更改陣列的內容,也可以透過傳入的位址直接操作資料。
#include
void toUpperCase(char str[]) {
for (int i = 0; str[i] != ' '; i++) {
if ('a' <= str[i] && str[i] <= 'z') {
str[i] = str[i] - ('a' - 'A');
}
}
}
int main() {
char text[] = "hello world";
toUpperCase(text);
printf("%s
", text); // 出力: HELLO WORLD
return 0;
}如此一來,即使想要修改陣列內容,因為它被視為指標,函式內的操作會反映到呼叫端。
使用 const 的唯讀參數
在 C 語言中,將陣列傳遞給函式時不會同時傳遞大小資訊。因此,為了安全操作,最好將大小也作為參數傳遞,這是最佳實踐。
void printChars(char str[], int size) {
for (int i = 0; i < size; i++) {
printf("%c ", str[i]);
}
printf("
");
}此外,使用 strlen 函式動態取得字串長度也是常見做法。但請注意,對未以 NUL 結尾的陣列不要使用此函式。
7. 實作範例: 字串的逆序顯示
如果在函式內不修改字串,建議使用 const char* 來明確表示為唯讀。
void printConstString(const char *str) {
printf("%s
", str);
}這樣可以防止意外的寫入,並清楚傳達函式的規格。
目的
在此,我們將利用迄今所學的 char配列 的知識,實際製作字串逆序顯示的程式。
範例程式碼
將使用者輸入的字串,從尾端向前端逐字元輸出。這對於陣列操作與字串長度取得、迴圈處理的練習非常有效。
說明
#include
#include
void printReversed(char str[]) {
int len = strlen(str);
for (int i = len - 1; i >= 0; i--) {
putchar(str[i]);
}
putchar('n');
}
int main() {
char text[100];
printf("請輸入字串:");
fgets(text, sizeof(text), stdin);
// 移除換行字元(fgets 使用時的對策)
size_t len = strlen(text);
if (len > 0 && text[len - 1] == 'n') {
text[len - 1] = '\0';
}
printf("逆序顯示為:");
printReversed(text);
return 0;
}執行範例
fgets- 輸入的末尾附加的 (換行字元)也不要忘記執行移除處理。
strlen()
應用提示
請輸入字串: OpenAI
逆序顯示為: IAnepO8. 常見錯誤與其對策
此處理可應用於字串的回文判定、堆疊結構的理解等,對學習演算法具有應用價值。此外,也可使用指標運算進行改寫,成為更高階的練習題材。
1. 忘記空字元(2. 緩衝區大小不足
)的遺漏
2. 緩衝區大小不足
在 C 語言中處理 char 陣列 時,從初學者到高手都有可能陷入的陷阱有幾個。這裡將具體說明常見錯誤及其防止對策・解決對策。
3. 字串常量的寫入
最常見的錯誤之一是忘記在字串末尾加上空字元(\0)。
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // ❌ 缺少結尾的'\0'
printf("%sn", str); // 未定義的行為對策:
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // ✅ 正確或者,使用字串常量會自動加入空字元。
4. fgets 的換行字元處理遺漏
strcpy和strcat等函式中,複製先的陣列大小不足會導致記憶體破壞(緩衝區溢位)。
char str1[5];
strcpy(str1, "Hello"); // ❌ 將 6 個字元複製到大小為 5 的陣列對策:
- 在複製目的地。 (例:「文字數 + 1」)
- 更安全的的使用也值得考慮
char str1[6];
strncpy(str1, "Hello", sizeof(str1) - 1);
str1[5] = '\0'; // 為了保險,明確在末尾加上空字元5. 指標與陣列的混淆
char *str = "Hello"; 這樣宣告的指標,指向不可寫入的區域的可能性。若對其寫入,會在執行時產生錯誤。
char *str = "Hello";
str[0] = 'h'; // ❌ 執行時產生 Segmentation fault對策:
char str[] = "Hello"; // ✅ 宣告為可寫入的陣列
str[0] = 'h';9. 總結
fgets 用來取得字串時,需要注意末尾會保留換行字元(n)。
fgets(str, sizeof(str), stdin);
// str 會包含類似 "Hellon\0" 的內容對策:
size_t len = strlen(str);
if (len > 0 && str[len - 1] == 'n') {
str[len - 1] = '\0';
}本篇文章學到的內容
因為外觀相似,char* 與 char[] 混為一談,可能導致未定義的行為。需要注意 大小取得 (sizeof) 的差異 以及 寫入可否的差異。
對未來學習的建議
在本篇文章中,我們針對「C語言的 char 陣列」從基礎到應用逐步解說。最後,回顧本篇內容,並介紹未來學習的指引。
本篇文章學到的內容
- char 陣列的角色與宣告方式 在 C 語言中沒有字串型別,因此處理字串時需要使用 char 型別的陣列。
- 字串文字列與空字元(
\0)的重要性 要表達字串,必須在末尾加入空字元。 - 使用標準函式庫函式的字串操作 , , , 等函式可使用,能有效處理字串。
- char 陣列與 char 指標的差異 陣列與指標雖相似但並非相同,且在記憶體結構、可否寫入等方面存在明確差異。
- 傳遞陣列給函式的方法與安全性考量 陣列實際上是以指標方式傳遞的,因此在寫入或尺寸管理時需要注意。
- 透過實踐範例與常見錯誤來鞏固理解 透過實際程式碼的應用與錯誤處理方法,學習了更實際的使用方式。
對未來學習的建議
了解 char 陣列的使用方式,是在 C 語言中理解記憶體操作基礎的第一步。在此學到的知識,可應用於以下的下一步。
- 指標運算
- 動態記憶體管理
mallocfree - 與結構體的組合
此外,閱讀他人撰寫的程式碼,可以吸收自己未曾具備的觀點與寫法。養成閱讀實際專案或 OSS(開源軟體)的習慣也非常有效。
C 語言自由度高,若未正確使用會有危險的一面,但只要細心累積基礎,就能成為非常強大的武器。對 char 陣列的理解就是第一步。請務必以本篇文章為參考,穩步提升技能。



