windows控制台默认不支持utf-8,根本原因是控制台使用ansi代码页(如cp936)而源文件多为utf-8编码,导致std::cout将utf-8字节流误作gbk解码而乱码;解决关键是让控制台识别utf-8:执行chcp 65001、调用setconsoleoutputcp(65001)、源文件保存为utf-8无bom,并启用msvc /utf-8编译选项。

Windows 控制台默认不支持 UTF-8,std::cout 输出中文会乱码
根本原因不是 C++ 本身的问题,而是 Windows 控制台(conhost)默认使用本地 ANSI 代码页(如 CP936),而你的源文件、字符串字面量大概率是 UTF-8 编码。两者不匹配,std::cout 就把 UTF-8 字节流当成了 GBK 解码,结果就是问号或方块。
关键动作不是改 C++ 代码,而是让控制台“知道自己正在收 UTF-8”:
- 运行程序前,在命令行执行
chcp 65001(切换控制台代码页为 UTF-8) - 在程序开头调用
SetConsoleOutputCP(65001)(需包含<windows.h></windows.h>) - 确保源文件保存为 UTF-8 无 BOM(BOM 会导致
std::string开头多出三个字节,输出异常)
std::wcout 配合 std::locale 不可靠,别硬刚
很多人试过 std::wcout + <code>std::locale(""),但在 Windows 控制台下极易失败——std::wcout 默认走的是宽字符路径,但 conhost 对 UTF-16 的支持有历史包袱,尤其 VS2019+ 默认禁用 /utf-8 时更不稳定。
实操建议直接放弃宽字符流方案,专注 UTF-8 字节流:
立即学习“C++免费学习笔记(深入)”;
- 字符串统一用
std::string,内容为 UTF-8 编码(编辑器设为 UTF-8 无 BOM) - 避免混用
std::cout和std::wcout,它们的缓冲区和 locale 独立,混用可能冲掉状态 - 如果必须用宽字符处理(比如调用 Windows API),转码用
WideCharToMultiByte(CP_UTF8, ...),而非依赖std::wcout
VS 编译选项 /utf-8 是必要但不充分条件
这个开关只影响编译器如何解释源文件中的字符串字面量,它不会改变控制台行为,也不会自动设置代码页。
启用方式(CMake 或项目属性里):
- MSVC:添加编译器参数
/utf-8 - CMake:在
target_compile_options()中加$<cxx>:/utf-8</cxx> - 注意:它不解决
std::cin输入中文的问题(输入仍受控制台当前代码页限制)
如果你没加 /utf-8,但源文件又是 UTF-8,那么 "你好" 在编译时就被误读成乱码字节,后续怎么设置控制台都白搭。
跨平台可移植的底线做法:只输出 ASCII,中文用资源文件或外部文本
真要稳定兼容 Linux/macOS/Windows 控制台,最省心的方式是回避终端编码问题本身:
- 日志、提示信息等固定文本,全部用英文(
"File not found") - 需要显示中文的地方,改用配置文件(JSON/TOML)或资源 DLL,运行时加载并按需转码
- 若必须终端输出中文,加一个启动检查:
GetConsoleOutputCP() != 65001时,友好提示用户先运行chcp 65001
Windows 控制台对 UTF-8 的支持从 Win10 1903 起才真正可用,老系统或远程桌面场景下,SetConsoleOutputCP 可能静默失败,这点容易被忽略。










