必须调用SetConsoleOutputCP(65001)将控制台输出编码设为UTF-8,同时确保源文件为UTF-8无BOM、编译器执行字符集设为UTF-8,三者对齐方可彻底解决乱码。

Windows 控制台默认用 GBK(代码页 936),而你的源文件大概率是 UTF-8 编码,printf 或 std::cout 输出的 UTF-8 字节流被控制台当 GBK 解码,乱码就必然发生。解决的关键不是“选一个方案”,而是让「源文件编码」「编译器执行字符集」「控制台代码页」三者对齐——最稳妥的路径是统一走 UTF-8。
怎么设置控制台为 UTF-8(Windows)
这是运行时必须做的一步,否则前面全白搭。只靠改源文件或编译选项,控制台仍按 GBK 显示,照样乱码。
-
SetConsoleOutputCP(65001)是最直接的方式,必须在main()开头调用,且要包含<windows.h></windows.h> - 顺带加上
SetConsoleCP(65001),否则std::cin输入中文也可能出错 - 不要用
system("chcp 65001"):它会打印一行提示(如活动代码页: 65001),污染输出;且在某些嵌入式终端或 CI 环境中可能失败 - 注意:此 API 仅 Windows 有效,Linux/macOS 控制台原生支持 UTF-8,无需额外设置
怎么让编译器正确处理 UTF-8 字符串字面量
即使源文件存成 UTF-8,MSVC 默认仍按 GBK 解析字符串字面量,导致 "你好" 被错误编码进二进制。GCC/Clang 则默认按 UTF-8 处理,但需显式指定执行字符集。
- MSVC 项目:在「属性 → C/C++ → 命令行 → 附加选项」里加
/execution-charset:utf-8(全局生效);或单文件加#pragma execution_character_set("UTF-8")(仅当前 .cpp 文件) - GCC/Clang:编译时加
-fexec-charset=UTF-8;CMake 中可用add_compile_options("-fexec-charset=UTF-8") - VS 中务必确认源文件保存为「UTF-8 无 BOM」:右键文件 →「高级保存选项」→ 编码选「UTF-8」,**不是「UTF-8 带签名」**(BOM 会导致 GCC 编译警告甚至解析异常)
为什么不能直接用 std::wstring 和 wcout
看起来很美:宽字符、Unicode、绕过多字节编码问题?但在 Windows 控制台下,std::wcout 实际依赖 WriteConsoleW,而它的行为受 locale 影响极大,且默认不启用,极易失效。
立即学习“C++免费学习笔记(深入)”;
- 必须先调
std::ios_base::sync_with_stdio(false)并std::wcout.imbue(std::locale("")),否则输出为空或崩溃 - 即使配置成功,
wcout在重定向到文件或管道时会退化为窄字符输出,行为不一致 - 跨平台时,Linux 的
wcout对 UTF-8 locale 支持不稳定,不如直接用 UTF-8 +cout可靠 - 真正需要宽字符的场景(如调用 Windows API 的
CreateWindowW),才应使用wchar_t;日常控制台输出,坚持 UTF-8 +cout更轻量、更可控
读写文件时中文乱码怎么破
控制台显示正常 ≠ 文件读写正常。很多问题出在 fopen / ifstream 默认用系统 locale 解码,而非你期望的 UTF-8。
- 写文件:用
std::ofstream时,**不要**用默认构造,改用二进制模式 + 手动写入 UTF-8 字节:file.write(str.c_str(), str.size()) - 读文件:同理,用二进制模式读出原始字节,再按 UTF-8 解析(或用
MultiByteToWideChar(CP_UTF8, ...)转宽字符) - 避免用
fopen("xxx.txt", "w")直接写中文字符串——它会触发 locale 依赖的编码转换,结果不可控 - 若必须用文本模式,MSVC 下可尝试
_setmode(_fileno(stdout), _O_U16TEXT)配合wprintf,但仅限控制台,不适用于文件
最容易被忽略的是:即使所有环节都设成 UTF-8,如果控制台字体不支持中文(比如默认的 Raster Fonts),依然显示方块。Windows 10/11 上建议手动把控制台字体改为「Lucida Console」或「Consolas」;旧系统可改用「NSimSun」。这个步骤没有代码可写,但缺了它,前面所有配置都白费。


















