C风格字符数组需显式指定长度或用初始化列表推导,如char s[] = "hello";,否则非法;易因忽略'\0'、越界、长度误判出错;推荐优先使用自动管理的std::string。

char数组定义时必须指定长度或用初始化列表推导
直接写 char s[]; 是非法的,编译器无法分配内存。要么显式给长度,比如 char s[10];,要么靠初始化内容自动算,比如 char s[] = "hello";(这时实际长度是6,含结尾的 '\0')。
常见错误是写成 char s[5] = "hello"; —— 看似5个字母,但字符串字面量自带 '\0',实际需要6字节,这会触发编译警告甚至截断。
- 安全做法:留足空间,如
char s[20] = "hello"; - 想省事又不越界:用
char s[] = "hello";,让编译器自己算 - 如果后续要拼接,记得预留空位,
char s[10] = "hi";后再用strcat很容易溢出
用std::string替代C风格字符串更安全
手动管理 char 数组容易踩内存越界、忘记 '\0'、长度误判这些坑。现代C++里,90%以上场景该用 std::string。
它自动管理内存、支持 + 拼接、能直接和C函数交互(通过 c_str() 或 data())。
立即学习“C++免费学习笔记(深入)”;
-
std::string s = "hello";—— 初始化简单,长度随内容变 - 传给C API时:用
s.c_str()获取以'\0'结尾的const char* - 注意:
s.data()在C++11中不一定以'\0'结尾,C++17起才保证,优先用c_str()
char*指向字符串字面量时不能修改内容
写 char* s = "hello"; 看起来像定义字符串,其实只是让指针指向代码段里的只读内存。后续若执行 s[0] = 'H';,运行时大概率崩溃(SIGSEGV)。
真正想改内容,得用数组或 std::string:
- 错的:
char* s = "hello"; s[0] = 'H'; - 对的:
char s[] = "hello"; s[0] = 'H'; - 或者:
std::string s = "hello"; s[0] = 'H';
从C函数读字符串到char数组要防缓冲区溢出
像 fgets、scanf 这类函数操作 char 数组时,不加长度限制等于埋雷。例如 scanf("%s", s); 遇到超长输入就写穿数组边界。
必须显式限制输入宽度:
-
fgets(s, sizeof(s), stdin);—— 推荐,自动带'\n'和'\0' -
scanf("%9s", s);—— 假设s长度为10,最多读9字符+1个'\0' - 用
std::getline(std::cin, str)更省心,没缓冲区风险
字符数组本身不记录长度,所有操作都依赖你记住容量和当前有效字符数——这点最容易被忽略,也是bug高发区。


















