C语言结构体字符数组成员字符串异常合并问题排查与解决
问题原因
C语言标准字符串以\0(ASCII值为0的空字符)作为结束标记,printf使用%s格式符打印字符串时,会从传入的内存起始地址开始逐字节读取,直到遇到第一个\0才会停止输出。
你的代码中存在两个直接触发问题的点:
- 结构体的
code成员定义为长度3的char数组,但初始化传入的"001"、"101"是C语言标准字符串字面量,本身占4字节空间:3个可见数字字符 + 编译器自动追加的1个\0终止符。长度为3的数组只能存下3个数字,没有预留位置存放\0。 - 结构体成员在内存中按定义顺序连续排布,
code数组结束的地址紧邻name数组的起始地址。printf读取code时找不到终止符,就会越过code的数组边界,直接读取相邻name成员的内存内容,直到碰到name字符串自带的\0才停止,最终表现为两个字段内容异常合并。
注意:这种越界访问属于C语言未定义行为,当前能输出合并内容只是内存排布刚好满足连续可读的条件,换编译选项、调整结构体成员顺序或者新增其他变量时,可能直接触发程序崩溃。
修复方案
两种方案都能解决问题,优先选第一种,通用性更强:
- 调整
code数组长度,预留空终止符的存储空间:将char code[3]改为char code[4],保证3位编码加终止符能完整存入数组。 - 如果业务上固定
code长度为3位、不想调整数组大小,打印时手动限定读取长度,将printf中对应code的格式符从%s改为%.3s,告诉printf最多读取3个字符就停止,不需要找\0。
修复后可直接运行的参考代码(采用调整数组长度方案)
#include <stdio.h> #include <stdlib.h> struct print { char code[4]; // 长度从3调整为4,预留\0存储位 char name[10]; }test[2]={"001","Alen","101","Paul"}; int main() { int x; for(x=0;x<2;x++) { printf("%s %s\n",test[x].code,test[x].name); } return 0; }
编译运行后输出完全符合预期:
001 Alen 101 Paul
内容的提问来源于stack exchange,提问作者LearnerC
相关产品推荐
相关产品推荐

