如何为message结构体中char[]自动补空终止符避免数组覆盖失效
问题根本原因
你出现乱码的核心原因是数组越界访问导致的未定义行为,具体问题点如下:
- 你的
message结构体中c成员定义为char c[5],合法下标范围是0~4,你代码中多次写c[5] = '\0',完全超出了数组的合法内存范围,写入的\0实际落到了相邻的内存地址 - 当你定义
message msg[2]数组时,两个message结构体在内存中是连续排布的,你给msg[0].c[5]写入的\0刚好落在msg[1]的起始内存位置,后续你给msg[1]赋值的时候自然会覆盖这个越界写入的\0,导致msg[0]的c数组没有合法终止符,打印时就会向后继续读取内存直到遇到随机的\0,就出现了乱码
修复方案
方案1:扩大char数组容量(最稳妥)
如果你要存最长5个字符的内容+终止符,直接把数组定义改成char c[6],这样就有合法位置存终止符,不会越界:
struct message { uint16_t x; bool b; char c[6]; // 改成长度6,足够存5个字符+1个终止符 };
修改后赋值逻辑可以改成更安全的通用写法,避免重复操作:
// 给c数组赋值示例 memcpy(msg1.c, str.c_str(), std::min(str.size(), sizeof(msg1.c)-1)); msg1.c[sizeof(msg1.c)-1] = '\0'; // 永远在数组最后一个合法位置写终止符
方案2:不修改结构体,构造字符串时指定长度
如果你不能修改结构体定义,可以在构造std::string的时候主动指定读取的长度,不需要依赖终止符:
// 把原来的std::string str(msgrecp[i].c);改成下面的写法 std::string str(msgrecp[i].c, sizeof(msgrecp[i].c));
这样即使没有终止符,也只会读取最多5个字符,不会读到后面的内存产生乱码。
额外优化点
你代码中计算buffer偏移的逻辑存在兼容性风险:header结构体的大小受内存对齐规则影响并不一定固定为8字节,建议统一用sizeof计算偏移,不要硬编码数值:
message* msgp = (message*)&buffer[sizeof(header)]; // 循环里的偏移也改成更通用的写法 msgp = (message*)((byte*)msgp + sizeof(message));
内容的提问来源于stack exchange,提问作者anes47
相关产品推荐
相关产品推荐

