Windows控制台默认使用GBK编码而非UTF-8,导致中文输出乱码;需执行chcp 65001或调用SetConsoleOutputCP(65001)切换,并确保字体支持中文及在外部CMD验证效果。

Windows 控制台默认不支持 UTF-8,std::cout 输出中文直接变问号或方块
根本原因不是 C++ 本身的问题,而是 Windows 控制台(conhost)默认使用本地 ANSI 编码(如 GBK),而源文件、编译器、标准库默认按 UTF-8 处理时就会错位。你写的是 "你好",但控制台以为是两段乱码字节。
- 确认当前控制台编码:运行
chcp,输出活动代码页: 936就是 GBK;输出65001才是 UTF-8 - 临时切到 UTF-8:在程序启动前执行
chcp 65001(仅对当前窗口生效) - 更可靠的做法是在程序开头调用
SetConsoleOutputCP(65001)(Windows API),需包含<windows.h> - 别只改输出——如果从文件读中文或用户输入中文,还得同步设
SetConsoleCP(65001)
std::wcout 配合 std::locale 仍可能失败,关键在 locale 初始化时机
很多人试过 std::wcout << L"你好" 却还是乱码,问题常出在没正确绑定本地化环境。C++ 标准库的 wcout 默认 locale 是 "C",不解析宽字符编码映射。
- 必须在首次使用
std::wcout前调用:std::ios_base::sync_with_stdio(false); std::wcout.imbue(std::locale("")); -
std::locale("")表示系统当前 locale(Windows 上对应控制面板→区域→管理→更改系统区域设置),不是空字符串 - 若系统 locale 是中文(如
Chinese_China.936),std::locale("")实际加载的是 GBK,此时wcout输出 UTF-16 宽字符串会再次错位——所以优先走 UTF-8 +SetConsoleOutputCP路线 - VS2019+ 可加编译选项
/utf-8,让源文件、字符串字面量、执行字符集统一为 UTF-8,减少隐式转换
跨平台代码里硬写 SetConsoleOutputCP 会编译失败,得加条件编译
Linux/macOS 终端原生支持 UTF-8,不需要也不认识 Windows API。直接写会导致 error: 'SetConsoleOutputCP' was not declared in this scope。
- 用预处理器隔离:
#ifdef _WIN32包裹 Windows 特有调用 - 别漏掉头文件:
#include <windows.h>仅在 Windows 下 include - 更稳妥的跨平台写法:检测运行时环境,或统一用
printf("%s", "你好")(前提是终端编码匹配且源文件保存为 UTF-8) - 注意 CMake 项目中,若用 MinGW 编译,
SetConsoleOutputCP可用,但某些旧版 MinGW 可能缺少声明,需加#define WIN32_LEAN_AND_MEAN再 include
VS 调试控制台和外部 CMD 窗口行为不一致,容易误判修复效果
Visual Studio 自带的“调试控制台”(Debug Console)不是标准 conhost,它对 UTF-8 的支持更弱,有时即使设置了代码页,仍显示异常;而你双击生成的 exe 在 CMD 中却正常。
立即学习“C++免费学习笔记(深入)”;
- 验证是否真修复:务必在外部 CMD 或 PowerShell 中运行可执行文件,而不是只看 VS 调试输出窗口
- VS 中可改用“Windows 终端”作为外部工具:项目属性 → 配置属性 → 调试 → 控制台窗口 → 设为
WindowsTerminal.exe(需已安装) - 若用 VS Code + Code Runner,默认也是内部终端,建议右键 → “在终端中运行”,并确保终端已执行过
chcp 65001 - 字体也影响显示:CMD 默认“Raster Fonts”不支持中文,需右键标题栏 → 属性 → 字体 → 改为
Lucida Console或Consolas
wcout 使用后才设 locale、以及只在 VS 调试窗口里测试。











