不能直接用sprintf,因其不检查缓冲区大小易致内存越界、崩溃或远程代码执行;应使用snprintf并传入正确缓冲区总字节数,配合返回值判断截断与否,跨平台需注意实现差异。
sprintf
因为 sprintf 不检查目标缓冲区大小,写超了就是内存越界——轻则程序崩溃,重则被利用执行任意代码。它连返回值都不告诉你写了多少字节,完全靠程序员自己算长度,实际项目里几乎没人敢用。
常见错误现象:sprintf 后接 std::string 构造或 strcpy 时出现乱码、段错误,或者在不同编

sizeof(buf) 计算容量——如果传的是指针(比如函数参数),sizeof 返回的是指针大小而非数组长度\0 占位snprintf 的正确调用姿势snprintf 是 C99 标准函数,会严格限制写入长度,并在缓冲区不足时自动截断+补 \0。关键点在于:**第二个参数必须是缓冲区总字节数(含结尾 \0)**,不是“还能写几个字符”。
示例:
char buf[64]; int n = snprintf(buf, sizeof(buf), "name: %s, age: %d", "Alice", 30); // n == 22(实际写入字符数,不含末尾 \0) // buf 安全,且以 \0 结尾
n >= sizeof(buf),说明内容被截断,可据此决定是否扩容重试n 为负(罕见,如编码错误),buf 仍会被置空(C11 起保证)_snprintf_s 或启用 /D_CRT_SECURE_NO_WARNINGS
std::string 的安全过渡方案C++ 没有原生 snprintf + std::string 绑定,但可以用两步法避免手动管理缓冲区:
snprintf(nullptr, 0, ...) 获取所需最小长度(C99 支持,返回不含 \0 的字符数)std::string 并用 &str[0](C++11 起保证连续)传给 snprintf
示例:
int len = snprintf(nullptr, 0, "id=%d, msg=\"%s\"", 123, "hello");
if (len >= 0) {
std::string s(len + 1, '\0'); // +1 for \0
snprintf(&s[0], s.size(), "id=%d, msg=\"%s\"", 123, "hello");
s.pop_back(); // 去掉末尾 \0,还原为纯内容
}
注意:s.size() 必须传给 snprintf,不能传 len + 1——否则可能因 snprintf 内部逻辑误判边界而出错。
snprintf 在不同平台表现并不完全一致:
n 返回实际需写长度(不含 \0),缓冲区不足时写满 size-1 字节再加 \0
nullptr 第二参数支持不完整,建议统一用临时栈缓冲区兜底sprintf 实现,必须自行做长度校验或引入 tinyprintf 类库真正麻烦的不是语法,而是跨平台时谁来保证 sizeof(buf) 算对了、谁来检查 snprintf 返回值、以及日志类封装里有没有把 \0 当内容一起发出去——这些地方一漏,安全就归零。