C++中不推荐使用scanf/printf,因其缺乏类型安全、易因格式符与参数类型不匹配导致崩溃或错误;应优先使用cin/cout,并在必须使用时严格校验格式符、避免混用流、检查返回值。

在 C++ 中直接用 scanf 和 printf 是可行的,但不是推荐做法——它们属于 C 标准库(),不支持 C++ 类型安全、重载或流操作语义,容易因格式符错配导致未定义行为。
为什么 scanf 容易崩溃或读错数据
scanf 要求格式字符串与变量地址严格匹配,且不检查类型。常见错误包括:
- 忘记加
&取地址(如对int x;写成scanf("%d", x)) - 用
%d读long long(应为%lld)或float(应为%f,但变量必须是float*,不是double*) - 输入缓冲区残留(如前一个
scanf("%d")后用户多按了回车,下一个scanf("%c")会直接读到换行符)
示例问题代码:
#includeint main() { int x; char c; scanf("%d", x); // ❌ 缺少 &x,栈破坏 scanf("%c", &c); // ❌ 可能读到上个输入留下的 \n }
printf 的格式符和参数类型必须一一对应
printf 不做运行时类型检查,传错类型会导致输出乱码、截断甚至段错误(尤其在 64 位系统上):
立即学习“C语言免费学习笔记(深入)”;
-
int用%d,long用%ld,long long用%lld -
size_t(如vector::size()返回值)应使用%zu,而非%d或%lu -
std::string::c_str()可传给%s,但直接传std::string对象会编译失败(无隐式转换)
错误示例:
std::vectorv = {1,2,3}; printf("size: %d\n", v.size()); // ❌ %d 匹配 int,但 size() 返回 size_t → 输出可能为负或截断
正确写法:
printf("size: %zu\n", v.size()); // ✅
混用 cin/cout 和 scanf/printf 前必须同步关闭
默认情况下,C++ 流(cin/cout)和 C 流(stdin/stdout)是独立缓冲的。混用会导致:
- 输出顺序错乱(
printf立即刷屏,cout可能延迟) - 输入阻塞(
cin >> x后再用scanf读字符,可能跳过预期输入)
解决方法:在 main() 开头加
std::ios::sync_with_stdio(false); // 解绑 cin/cout 与 stdin/stdout cin.tie(nullptr); // 解绑 cin 与 cout
注意:一旦调用该设置,就不能再混用 cin 和 scanf(否则行为未定义)。若已用 scanf,就全程用 C 风格;若用 cin,就别碰 scanf。
替代方案:什么时候真该用 scanf/printf
仅在以下场景可考虑保留 C 风格 I/O:
- ACM/ICPC 等 OJ 平台要求极致输入速度(关闭同步后
scanf比cin快约 2–3 倍) - 对接遗留 C 接口,或日志函数只接受
printf-style 格式串 - 需要精确控制浮点数输出格式(如
printf("%.6f", x)比std::fixed 更简洁)
但即便如此,也要确保:
- 所有格式符与参数类型完全匹配
- 不混用 C/C++ 风格流
- 对用户输入做容错处理(如检查
scanf返回值是否等于期望读取项数)
例如安全读整数:
int x;
if (scanf("%d", &x) != 1) {
// 输入失败,处理错误
}
真正麻烦的不是语法,而是格式符和类型的隐式契约——它不报错,只在某个平台、某种优化级别下突然崩掉。











