源文件必须存为 UTF-8 无 BOM,否则 VS 默认按 GBK 等系统编码保存中文,将导致 std::cout 输出乱码。

源文件必须存为 UTF-8 无 BOM
这是所有后续设置生效的前提。VS 中默认可能按系统区域设置(如 GBK)保存中文,导致 std::cout 编译后输出乱码。必须手动选「文件 → 另存为 → 小三角 → 高级保存选项」,编码选 UTF-8,**不能选 UTF-8 with BOM**。
常见错误现象:
- 代码里写的是中文,但编译时报错:`error C2001: newline in constant` 或 `warning C4819: The file contains a character that cannot be represented in the current code page`
- Linux/macOS 下编译通过,Windows 下报错或显示方块
验证方式:用 VS Code 或 Notepad++ 打开源文件,右下角看编码标识;或用命令行 file -i your_file.cpp(Linux/macOS)确认是否为 charset=utf-8。
编译器要明确告诉它“源码是 UTF-8”
即使文件存对了,编译器仍可能按本地代码页解析。必须显式指定输入字符集:
- GCC/Clang:
-finput-charset=UTF-8(推荐加到CXXFLAGS) - MSVC:
/source-charset:utf-8(Visual Studio 项目属性 → 配置属性 → 常规 → 字符集 → 选“使用 Unicode 字符集”还不够,必须额外加这个开关)
不加的话,MSVC 在中文 Windows 上默认按 GBK 解析源码,"你好" 会被当成两个非法字节,触发警告或静默截断。
Windows 控制台输出前必须调用 SetConsoleOutputCP(CP65001)
这是 Windows 特有的坑:cmd/powershell 默认输出代码页是 CP936(GBK),而你的 std::cout 输出的是 UTF-8 字节流,直接喂给控制台就会乱码。
正确做法:
- 在
main()开头、**任何std::cout输出之前**调用:SetConsoleOutputCP(CP65001); - 如果还要读中文输入,顺带加一句:
SetConsoleCP(CP65001); - 记得包含头文件:
#include
常见错误:
- 放在
std::cout后面——无效,控制台已按旧编码开始渲染 - 用
system("chcp 65001")替代——只改子进程 cmd 的代码页,不影响当前进程 stdout 句柄 - 没加
std::ios_base::sync_with_stdio(false);——C++ 流与 C stdio 缓冲可能不同步,加剧乱码
跨平台时别依赖 std::cout 直接输出中文字符串
Linux/macOS 终端原生吃 UTF-8,Windows 则需上述 WinAPI 补丁,二者行为不一致。更稳的写法是封装一层:
- Windows 路径:用
WriteConsoleW+MultiByteToWideChar转宽字符输出 - Unix 路径:直接
write(1, utf8_bytes, len) - 或者统一用
std::wcout,但必须先调用:std::wcout.imbue(std::locale(""));(且确保终端 locale 支持 UTF-8)
最易被忽略的一点:即使你做了全部设置,旧版 Windows 7 的 cmd 对 CP65001 支持不完整,某些组合字符仍会崩。真要兼容老环境,要么换用 PowerShell / Windows Terminal,要么干脆避免在控制台打中文,改用日志文件输出。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











