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

C語言字符數組與字符串全攻略:定義、初始化、存儲差異、輸入輸出與常用函數

     編輯:C 語言入門

一、字符數組基礎:定義與初始化

1. 定義語法

char arr[常量表達式];          // 未初始化,內容不定
char arr[SIZE] = {'a','b','c'}; // 列表初始化
char arr[] = "Hello";           // 字符串字面量初始化(含隱式 \0)

關鍵點:數組長度必須為編譯期常量(C99 允許 VLA,但不推薦用於字符串)。

2. 三種初始化形式詳解

形式代碼示例內存佈局說明
全量指定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

二、字符串常量 vs 字符數組:存儲本質差異

// 字符串常量(唯讀數據段 .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。

經典陷阱:\0 終止符的作用

printf("Hello\0World"); // 輸出 "Hello" —— 遇到 \0 即停止
char s[] = "Hello\0World";
printf("%s", s);        // 同理,只打印 "Hello"
printf("%zu", strlen(s)); // 返回 5,而非 11

三、字符串變量:本質是以 \0 結尾的字符數組

定義等價形式

char str1[15] = {"Hello"}; // 帶花括號
char str2[15] = "Hello";   // 無花括號(常用)
char str3[] = "Hello";     // 自動推導長度(含 \0,長度 6)

四、格式化輸入輸出:%s 的行為細節

函數格式符行為注意事項
scanf%s跳過前導空白,讀取至下一空白(空格/換行/制表/\0)極易溢出,無長度限制。實戰用 %19s (長度-1)
printf%s從地址輸出至遇到 \0無 \0 導致越界讀取,極度危險

安全輸入最佳實踐

char buf[20];
scanf("%19s", buf);        // C99: 限制寬度,預留 1 字節給 \0
// 或更安全:
fgets(buf, sizeof(buf), stdin); // 讀整行含 \n,需手動去除

五、字符串長度計算:strlen 陷阱

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>)

函數原型作用關鍵前提
strlensize_t strlen(const char *s)有效長度(不含 \0)s 必須以 \0 結尾
strcpychar *strcpy(char *dest, const char *src)複製含 \0dest 空間必須 ≥ src 長度+1,否則溢出
strncpychar *strncpy(char *dest, const char *src, size_t n)複製至多 n 字符若 src 短於 n,補 \0;否則 不自動添加 \0
strcatchar *strcat(char *dest, const char *src)追加 src 到 dest 末尾dest 必須有足夠空間且以 \0 結尾
strcmpint strcmp(const char *s1, const char *s2)字典序比較返回 <0, =0, >0;逐字節比較,遇異即止

七、避坑指南總結

  1. 永遠為 \0 預留空間:定義數組長度 = 最大字符串長度 + 1。
  2. 拒絕裸 scanf("%s")/strcpy:使用寬度限制或安全版本(strncpy_s、strcpy_s C11 可選)。
  3. 區分「字符數組」與「字符串」:前者是容器,後者是約定(以 \0 結尾)。
  4. 字符串字面量不可修改:char *p = "abc"; p[0]='x'; // UB,改用 char p[] = "abc";。
  5. 嵌入 \0 會截斷所有標準字符串函數:二進制數據請用 memcpy/memcmp 並顯式傳長度。

掌握字符數組與字符串的內存佈局、\0 約定、輸入輸出邊界,是寫出健壯 C 代碼的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved