Windows控制台输出中文乱码的根本原因是控制台默认GBK编码(代码页936)与UTF-8源文件不匹配,且std::cout未做编码转换;需同时满足UTF-8-BOM保存源文件和SetConsoleOutputCP(65001)设置控制台为UTF-8。

Windows 控制台输出中文乱码的根本原因
根本不是 C++ 语言本身的问题,而是 Windows 控制台默认使用 GBK 编码(代码页 936),而你源文件保存为 UTF-8(尤其 VS 默认新建文件是 UTF-8 with BOM),std::cout 直接写入字节流时没做转换,控制台就按 GBK 解释 UTF-8 字节 —— 自然显示为“锘忋€滄”这类乱码。
关键点:setlocale(LC_ALL, "") 在 Windows 上只影响 C 风格宽字符函数(如 wprintf),对 std::cout 和窄字符流完全无效;它也不能改变控制台的活动代码页。
VS 中正确保存和编译 UTF-8 源文件
Visual Studio 默认新建 .cpp 文件是 UTF-8 with BOM,但若手动复制粘贴过中文、或从网页粘入,可能变成 UTF-8 without BOM —— 这会导致 cl.exe 编译时报错 C2001: newline in constant 或输出异常。
- 在 VS 中:用「文件 → 高级保存选项」确认编码为
UTF-8 with signature (UTF-8-BOM) - 命令行编译时加
/utf-8参数(VS 2015+ 支持):cl /EHsc /utf-8 main.cpp - 不加
/utf-8时,编译器会把源文件按当前系统 ANSI 代码页(如 GBK)解析,中文字符串字面量会被错误转义
让 std::cout 在 Windows 控制台正确输出 UTF-8 中文
必须同时满足两个条件:源文件是 UTF-8-BOM + 控制台代码页设为 UTF-8。缺一不可。
立即学习“C++免费学习笔记(深入)”;
- 程序启动时调用
SetConsoleOutputCP(65001)(需#include) - 确保控制台字体支持中文(如 “Lucida Console” 或 “Consolas” 不行,“新宋体”、“等线” 可以;PowerShell 默认字体通常不支持,建议用 CMD 或修改终端设置)
-
setlocale(LC_ALL, "Chinese_China.936")或""对std::cout无作用,别白费劲 - 示例片段:
#include
#include int main() { SetConsoleOutputCP(CP_UTF8); std::cout << "你好,世界!" << std::endl; // 源文件必须是 UTF-8-BOM }
跨平台兼容写法(避免 Windows 特有 API)
如果想一份代码在 Linux/macOS 也能跑,就不能依赖 SetConsoleOutputCP。此时更稳妥的做法是:放弃控制台直接输出 UTF-8,改用宽字符流 + std::wcout,并配合 _setmode(Windows)或 locale 设置(POSIX)。
- Windows 下必须调用
_setmode(_fileno(stdout), _O_U16TEXT)(+) - Linux/macOS 下只需
std::setlocale(LC_ALL, "")+std::wcout,且终端需支持 UTF-8(绝大多数现代终端默认满足) - 字符串字面量要写成
L"你好",且注意std::wcout的缓冲行为,常需 - 混合窄/宽流会破坏状态,二者不要混用
真正麻烦的是字体和终端能力 —— 即使编码全对,终端不支持渲染 UTF-8 中文,照样显示方块或空白。这点比编码设置更难自动化修复。










