Windows下需调用SetConsoleOutputCP(CP65001)设置UTF-8输出编码,且必须在首次输出前调用;Linux/macOS原生支持UTF-8,无需额外设置;跨平台时还须确保源文件为UTF-8无BOM、终端字体支持对应字符。

Windows下用SetConsoleOutputCP切换控制台输出编码
在Windows命令行(cmd或PowerShell)中,默认输出编码通常是GBK(CP936)或系统区域设置对应的代码页,导致std::cout输出UTF-8字符串时显示乱码。直接调用SetConsoleOutputCP可强制指定输出编码,比如设为UTF-8(CP65001):
#include <windows.h>
#include <iostream>
int main() {
SetConsoleOutputCP(CP65001); // 切换为UTF-8
std::cout << "你好,世界!\n";
return 0;
}
注意:该函数仅影响当前进程的输出行为,不改变cmd窗口本身的默认代码页;且必须在首次输出前调用,否则可能无效。
Linux/macOS不需要也不支持SetConsoleOutputCP
Unix-like系统终端原生以UTF-8为默认编码,std::cout输出UTF-8字节流即可正常显示,无需额外设置。若出现乱码,问题通常出在:
- 源文件保存编码不是UTF-8(如含BOM或ANSI)
- 终端本身未启用UTF-8(检查
locale命令输出中LANG是否含utf8) - 程序中误用了
wcout但没调用std::wcout.imbue(std::locale(""))
没有等效于SetConsoleOutputCP的POSIX API——编码由终端解释,程序只负责输出正确字节。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
跨平台输出UTF-8字符串的可靠写法
Windows上即使调用了SetConsoleOutputCP(CP65001),仍可能因旧版cmd不完全兼容而失败(尤其Win7)。更稳妥的做法是:
- 编译时确保源文件为UTF-8无BOM格式
- Windows下优先使用
WriteConsoleW配合MultiByteToWideChar转宽字符输出 - 避免依赖
std::cout直接输出非ASCII字符串,改用封装函数统一处理 - 若必须用
std::cout,需同时调用SetConsoleOutputCP(CP65001)和SetConsoleCP(CP65001)(后者影响输入)
例如:
SetConsoleOutputCP(CP65001); SetConsoleCP(CP65001); std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr);
常见错误:system("chcp 65001")不可靠
有人尝试用system("chcp 65001")切换代码页,这存在几个问题:
- 仅修改子进程(cmd)的代码页,不影响当前C++进程的
stdout句柄行为 - 执行后无法保证后续
std::cout立即生效(缓冲、同步问题) - Linux/macOS下该命令不存在,破坏跨平台性
- 权限受限环境可能禁止
system调用
真正起作用的是Windows API对控制台句柄的设置,不是shell命令。
最易被忽略的一点:即使所有设置都正确,如果终端字体不支持对应Unicode字符(比如用“Lucida Console”显示中文),依然会显示方块——编码只是前提,字体才是最终渲染环节。

















