sprintf将int转字符串易致缓冲区溢出,因不检查目标数组大小;安全做法是用snprintf并传入sizeof(buf),或改用std::to_string等c++安全替代方案。

用 sprintf 把 int 转成字符串存进字符数组,得先保证空间够用
直接调 sprintf(buf, "%d", num) 看似简单,但最常出问题的是缓冲区溢出——buf 太小,比如只开 char buf[4] 却去存 -128(占 5 字节:'-' + '1' + '2' + '8' + '\0')。C++ 不做运行时长度检查,写超了就踩内存。
-
int最大是2147483647(10 位),最小是-2147483648(11 位),所以安全起见,char buf[12]是底线 - 如果不确定
int范围(比如用的是long long或跨平台代码),改用snprintf更稳妥:snprintf(buf, sizeof(buf), "%d", num) - 别用
sprintf(buf, "%d", num)后再手动加\0——它已经写了
sprintf 的返回值不是成功标志,而是写入字符数(不含 \0)
很多人误以为返回非负值就代表成功,其实只要 buf 地址合法、格式串合法,sprintf 总会返回一个非负整数(哪怕缓冲区不够,它仍会算“假想中”该写多少字)。真要判断是否截断,得靠 snprintf:
int len = snprintf(buf, sizeof(buf), "%d", num);
if (len >= (int)sizeof(buf)) {
// 截断了,buf 不完整
}
而 sprintf 没这个能力,纯靠你预估大小。
格式说明符选错会导致输出异常或未定义行为
常见错误是混用类型和说明符,比如把 unsigned int 用 %d 打印,或把 long 用 %d 打印(在 Windows MSVC 下 long 是 4 字节,但 Linux x86_64 下是 4 字节,x86_64 g++ 下 long 是 8 字节)。
-
int→%d或%i(安全) -
unsigned int→%u(不用%d,否则高位被解释为符号位) -
long→%ld,long long→%lld(Clang/GCC),MSVC 用%I64d - 十六进制用
%x,八进制用%o,都需匹配实际类型
现代 C++ 更推荐用 std::to_string 或 std::format 替代 sprintf
sprintf 是 C 风格,不类型安全、无自动长度保护、不能拼接 std::string。C++11 起有更稳的替代:
-
std::string s = std::to_string(123);—— 简单直接,类型安全,但不支持格式控制(如补零、进制) - C++20
std::string s = std::format("{}", 123);或std::format("{:04}", 42)—— 功能强、安全、可读性好 - 若必须用 C 风格(如嵌入式、对接旧 API),优先选
snprintf,且永远传入sizeof(buf),别用硬编码数字
真正难的不是怎么写那行 sprintf,而是想清楚:这里到底需不需要手动管理缓冲区?有没有更少出错的路径?
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











