字符串基础
C 语言中的字符串是以空字符 \0 结尾的字符数组。字符串字面量 "Hello" 自动在末尾添加 \0,存储在只读数据段。理解字符串的存储方式和字符数组的关系,是正确处理字符串操作的基础。
字符串的表示
/* 字符数组初始化 */
char str1[] = "Hello"; /* 大小为 6:'H','e','l','l','o','\0' */
/* 显式字符初始化 */
char str2[] = {'H', 'e', 'l', 'l', 'o', '\0'}; /* 等价 */
/* 指定大小 */
char str3[6] = "Hello"; /* 正确:6 个位置 */
char str4[5] = "Hello"; /* 错误:'\0' 被截断 */
字符串字面量
字符串字面量存储在只读数据段,修改它是未定义行为:
char *p = "Hello";
p[0] = 'h'; /* 未定义行为!可能崩溃 */
/* 正确:复制到可修改的数组 */
char str[] = "Hello";
str[0] = 'h'; /* 合法 */
字符串字面量的类型是 char[],在大多数表达式中退化为 char *。
字符串长度
字符串长度是字符数(不含 \0):
#include <string.h>
char str[] = "Hello";
printf("%zu\n", strlen(str)); /* 5 */
printf("%zu\n", sizeof(str)); /* 6(含 '\0') */
strlen 遍历字符串直到 \0,时间复杂度 O(n)。sizeof 在编译时计算数组大小。
空字符串
char empty1[] = ""; /* 大小为 1:{'\0'} */
char empty2[] = { '\0' }; /* 等价 */
strlen(empty1); /* 0 */
sizeof(empty1); /* 1 */
字符串数组
/* 指针数组 */
char *words[] = {"Hello", "World", "C"};
/* 二维字符数组 */
char names[][10] = {"Alice", "Bob", "Charlie"};
/* 访问 */
printf("%s\n", words[0]); /* Hello */
printf("%c\n", names[1][0]); /* B */
char *words[] 存储的是指针,字符串字面量可能共享。char names[][10] 存储的是字符的副本。
常见错误
忘记 \0:
char str[5] = {'H', 'e', 'l', 'l', 'o'}; /* 没有 '\0' */
strlen(str); /* 未定义行为:找不到 '\0' */
/* 正确 */
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
修改字符串字面量:
char *p = "Hello";
p[0] = 'h'; /* 未定义行为 */
/* 正确 */
char str[] = "Hello";
str[0] = 'h';
缓冲区太小:
char str[5];
strcpy(str, "Hello"); /* 越界:需要 6 字节 */
/* 正确 */
char str[6];
strcpy(str, "Hello");
最佳实践
- 字符串数组大小至少为字符串长度 + 1
- 需要修改时用字符数组,不要用指针指向字符串字面量
- 用
strlen获取长度,sizeof获取数组大小 - 字符串操作始终确保
\0终止 - 使用带长度限制的字符串函数(
strncpy、strncat、snprintf)