为什么C语言初始化char字符串时会出现自动拼接的异常现象?
问题原因及底层原理
核心规则
C语言标准规定:字符串本质是以\0(空字符,ASCII值为0)作为结束标记的char类型数组。使用printf的%s格式符输出字符串时,程序会从传入的首地址开始向后读取内存字节,直到遇到\0才会停止输出。如果数组中没有存储\0,程序就会越界读取数组后方相邻的内存内容,直到碰巧读到\0为止。
第一次代码异常的具体原因
你第一次声明的l[6]、m[6]存在长度不足的问题:
- 字符串字面量
"stop c"、"nice c"的可见字符都是6个(s/t/o/p/空格/c 共6个),你指定数组长度为6时,编译器只会将这6个可见字符存入数组,没有多余空间存储\0,也不会主动补\0。 - 而你声明的
k[]没有指定长度,编译器会自动计算所需空间:6个可见字符+1个\0,最终k数组长度为7,末尾自动带有\0结束标记。 - C语言中函数内声明的局部数组会在栈内存中连续排布,顺序通常和声明顺序相反(也就是
m在低地址,然后是l,然后是k),所以读取l时越界就会读到后面k的内容,读取m时越界会读到后面l和k的内容,最终就出现了你看到的字符串拼接的异常输出。
改成长度7后恢复正常的原因
当你把l、m的长度改为7后,6个可见字符存入数组后还剩1个字节的空间,编译器会自动在这个位置填充\0,三个数组都有了属于自己的结束标记。printf输出每个字符串时,读到数组末尾的\0就会停止,不会再越界读取后方内存,因此输出恢复正常。
补充注意事项
- 声明固定长度的char数组存储字符串时,数组长度至少要比可见字符数多1,预留空间存储
\0。 - 如果没有特殊需求,直接写
char 数组名[] = "字符串字面量"让编译器自动计算数组长度即可,能避免手动指定长度漏算\0的问题。 - 你遇到的这种越界读内存属于C语言的未定义行为,不同编译器、不同运行环境下表现可能不一致,除了字符串拼接外,也可能出现乱码、程序崩溃等异常结果。
内容的提问来源于stack exchange,提问作者Mrinaal
相关产品推荐
相关产品推荐

