C++中从字符串与变量构建字符数组报错求助
问题分析与解决
核心问题
你代码里的auto mstr = (char*)"";是错误根源:
- 字符串字面量
""是只读的,且仅占1字节(存储终止符\0),没有空间存放后续拼接的浮点数和换行符,导致sprintf_P写入时缓冲区溢出,触发警告。 - 用
sprintf_P(mstr, PSTR("%s %f"), mstr, ...)属于未定义行为——同时将目标缓冲区作为格式化源参数,读写同一内存的顺序不确定,会导致不可预测的结果。
解决方案
方案1:使用固定大小字符数组(C风格,适合嵌入式环境)
定义一个足够大的可写缓冲区,用安全的方式拼接内容:
// 定义64字节缓冲区,足够容纳浮点数、换行符及终止符 char mstr[64] = {0}; // 先写入浮点数(初始缓冲区为空,不需要%s拼接) sprintf_P(mstr, PSTR("%f"), z_values[x][y] * 1000); // 拼接换行符,用strcat_P更高效(针对PROGMEM字符串) strcat_P(mstr, PSTR("\n")); // 传递给函数 RTS_SndData(mstr, AUTO_BED_LEVEL_MESH_VP);
如果要多次拼接且避免溢出,推荐用snprintf_P限制写入长度:
char mstr[64] = {0}; // 写入浮点数,确保不超过缓冲区大小 snprintf_P(mstr, sizeof(mstr), PSTR("%f"), z_values[x][y] * 1000); // 拼接换行符,计算剩余空间 size_t current_len = strlen(mstr); snprintf_P(mstr + current_len, sizeof(mstr) - current_len, PSTR("\n"));
方案2:使用C++ std::string(更接近PHP的字符串操作)
如果Marlin环境支持C++标准库,用std::string更安全,无需手动管理缓冲区:
#include <string> // 若未包含需添加 std::string mstr; // 先将浮点数格式化为字符串,存入临时缓冲区 char float_buf[32]; sprintf_P(float_buf, PSTR("%f"), z_values[x][y] * 1000); // 像PHP一样直接拼接 mstr += float_buf; mstr += "\n"; // 转换为C风格字符串传递给函数 // 若RTS_SndData接受const char*,用mstr.c_str() // 若必须非const char*,用&mstr[0](C++11及以后)或const_cast RTS_SndData(const_cast<char*>(mstr.c_str()), AUTO_BED_LEVEL_MESH_VP);
关键注意事项
- 永远不要用字符串字面量(如
"")作为可写缓冲区,它们存放在只读内存区,修改会导致崩溃。 - 避免在
sprintf/sprintf_P中同时将目标缓冲区作为源参数,这属于未定义行为。 - 嵌入式环境中优先用带长度限制的
snprintf_P,防止缓冲区溢出引发硬件故障。
内容的提问来源于stack exchange,提问作者johncarlson21
相关产品推荐
相关产品推荐

