根本原因是Windows控制台默认使用GBK等ANSI编码,而源文件多为UTF-8,cout输出的UTF-8字节流被控制台按GBK错误解码导致乱码。

Windows 控制台默认编码不是 UTF-8,cout 输出中文会乱码
根本原因不是 C++ 本身的问题,而是 Windows 控制台(conhost)默认使用本地 ANSI 编码(如 GBK),而你的源文件大概率保存为 UTF-8(尤其用 VS Code、CLion 等编辑器时)。cout 把 UTF-8 字节流原样扔给控制台,控制台却按 GBK 解码,结果就是“你好”变成“浣犲ソ”这类乱码。
常见错误现象:std::cout 显示问号、方块或完全看不懂的字符;用 <code>chcp 查看当前代码页是 936(GBK)但源码是 UTF-8。
- VS 2019/2022 默认新建项目保存为 UTF-8 with BOM,但控制台不认 BOM,只按代码页解码
- 用
chcp 65001临时切到 UTF-8 有效,但每次新开终端都要重输,且某些旧版 Windows 或远程终端不支持 - 在 C++ 中调用
SetConsoleOutputCP(65001)可以设输出编码,但必须配合SetConsoleCP(65001)(输入)才完整,否则std::cin仍可能出问题
VS 编译器需显式指定源文件编码为 UTF-8,否则 cl.exe 按系统 ANSI 解析字符串字面量
即使你把 .cpp 文件存成 UTF-8,MSVC 默认仍按系统区域设置(如简体中文 = GBK)读取源码。这意味着 "你好" 这四个汉字在编译时就被错误解释为 GBK 字节,再转成 UTF-8 输出就彻底错乱。
解决方式:给编译器加参数 /utf-8(VS 2015 Update 2+ 支持)。
立即学习“C++免费学习笔记(深入)”;
- VS IDE 中:项目属性 → 配置属性 → 常规 → “字符集”选“使用 Unicode 字符集”(这影响
TCHAR,不解决源码编码)→ 再进“C/C++” → “命令行” → 在“附加选项”里加/utf-8 - 命令行编译:用
cl /utf-8 hello.cpp,不能只靠chcp 65001 - 不用
/utf-8而改用#pragma execution_character_set("utf-8")是无效的——它只影响字符串字面量的运行时编码行为,不改变编译器读源码的方式
std::wcout + std::locale 是更健壮的方案,但必须同时处理控制台和编译器
用宽字符流绕过多字节编码转换问题,本质是让 C++ 标准库和 Windows API 在 Unicode 层面直接对接。但这要求每一步都对齐:
- 源文件必须存为 UTF-8(或 UTF-16 LE,但 UTF-8 更通用),并确保编译器用
/utf-8正确读取 - 代码中用
L"你好"定义宽字符串,或用std::wstring_convert(C++17 已弃用)/std::from_bytes(C++23)做转换 - 必须调用
std::wcout.imbue(std::locale(""));让宽流绑定系统 locale,否则wcout仍可能走窄字符 fallback - 还要调用
SetConsoleOutputCP(CP_UTF8)和SetConsoleCP(CP_UTF8),否则 Windows 控制台不接收 UTF-16 输出(wcout实际发的是 UTF-16)
示例关键片段:
#include <windows.h>
#include <iostream>
#include <locale>
int main() {
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
std::wcout.imbue(std::locale(""));
std::wcout << L"你好,世界!" << std::endl;
}
跨平台项目别依赖 chcp,它只在 Windows cmd/powershell 有效
chcp 65001 是纯 shell 行为,对 VS 的“输出窗口”、WSL、Docker 容器、CI 环境(如 GitHub Actions 的 ubuntu-latest)完全无效。硬写 system("chcp 65001 > nul"); 不仅丑陋,还会在非 Windows 平台编译失败或运行崩溃。
真正可移植的做法只有两个:
- 统一用 UTF-8 源码 +
/utf-8编译参数 +SetConsoleOutputCP(65001)(Windows 分支)+ 控制台字体支持(如“Lucida Console”或“Consolas”) - 或者放弃控制台直出,把中文输出转成 HTML / JSON / 日志文件,交给浏览器或专用查看器渲染
- Mac/Linux 下一般无此问题,因为终端默认 UTF-8,但要注意
LANG环境变量是否为en_US.UTF-8类值,而非C
最易被忽略的一点:字体。即使所有编码都对了,如果控制台用的是不支持中文的字体(比如默认的 Raster Fonts),照样显示方块。右键控制台标题栏 → “属性” → “字体”,选“Lucida Console”或“Consolas”。



















