windows下最稳方案是setconsoletextattribute,需先getstdhandle获取句柄,颜色为前景背景组合,需手动重置,默认色为foreground_red|green|blue,非线程安全;linux/macos直接用ansi转义序列如\033[31m。

Windows下用SetConsoleTextAttribute最稳
Windows原生控制台不支持ANSI转义序列(除非开启虚拟终端处理,但Win10 1607前默认关),直接输出\033[31m大概率显示乱码或啥也不变。用SetConsoleTextAttribute是兼容性最好、行为最确定的方式。
实操建议:
- 必须先调用
GetStdHandle(STD_OUTPUT_HANDLE)拿到句柄,不能硬写stdout - 颜色值是前景+背景的组合,比如
FOREGROUND_RED | FOREGROUND_INTENSITY是亮红色文字 - 每次改色后,后续所有输出都沿用该颜色,得手动重置回默认(
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) - 别在子线程里并发调用它——这个API不是线程安全的
Linux/macOS用ANSI转义序列就行
绝大多数终端(xterm、iTerm2、GNOME Terminal、WSL)都默认支持\033[...m,不用额外初始化。
常见错误现象:程序在IDE内置终端(如VS Code、CLion)里没颜色,但在系统终端里正常——大概率是IDE没把TERM设对,或禁用了ANSI解析(可查设置里的“Enable ANSI colors”)。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 常用颜色速记:
\033[31m(红)、\033[32m(绿)、\033[1;33m(亮黄)、\033[0m(重置) - 避免手写数字,用宏或内联函数封装,比如
#define RED "\033[31m",否则容易漏\033[0m导致后续全部变色 std::cout 比逐字节写<code>\033更安全
跨平台方案别自己造轮子
真要同时跑Windows/Linux/macOS,且不想写条件编译,就别硬凑一套“统一接口”——容易漏掉Windows老版本的句柄失效、ANSI在ConEmu里的双模式切换等问题。
实操建议:
- 直接用成熟小库,比如
colored(header-only,C++17)或fmt::color(需fmt库) - 如果只用
std::cout,fmt最省心:fmt::print(fg(fmt::red), "error: {} \n", msg); - 拒绝“用
system("color 0C")”这类方案——它改的是整个窗口配色,不可逆,且会闪屏
别忽略输出重定向和日志场景
颜色代码本质是控制字符,一旦std::cout被重定向到文件或管道(比如./a.out > log.txt),这些字符就变成垃圾文本,污染日志。
实操建议:
- 检测是否为真实终端:
_isatty(_fileno(stdout))(Windows)、isatty(STDOUT_FILENO)(POSIX) - 环境变量优先级更高:很多CI/CD环境(GitHub Actions、GitLab CI)会设
NO_COLOR=1,应主动检查并跳过颜色输出 - 日志库(如
spdlog)通常自带ansi_color_formatter开关,开之前先确认stdout是否连着终端
if分支很容易漏掉边界情况。











