windows下需用setconsoletextattribute设色,linux/macos优先用ansi;跨平台应封装统一接口而非预处理器宏,运行时检测终端能力比编译时判断更可靠。

Windows 下用 SetConsoleTextAttribute 改颜色最直接
Windows 控制台不支持 ANSI 转义序列(除非启用虚拟终端处理,但默认关着),所以得调系统 API。核心是 SetConsoleTextAttribute,它作用于当前控制台句柄,改的是后续输出的文本颜色。
常见错误是没获取正确句柄,或传错参数——比如把前景色和背景色位掩码搞混,或者用了已废弃的 GetStdHandle(STD_OUTPUT_HANDLE) 却没检查返回值是否有效。
-
SetConsoleTextAttribute的第二个参数是 16 进制组合值,例如FOREGROUND_RED | FOREGROUND_INTENSITY表示亮红色文字 - 必须在每次输出前调用,它不持久;如果中间穿插了其他库的输出(比如
std::cout混用 C 风格printf),颜色可能意外重置 - Win10 1511+ 可以开启虚拟终端支持,让 ANSI 生效,但需手动调用
SetConsoleMode启用ENABLE_VIRTUAL_TERMINAL_PROCESSING,否则\033[31m会原样打印出来
Linux/macOS 下优先用 ANSI 转义序列
绝大多数 Unix-like 终端原生支持 ANSI,写法简单、移植性好。关键不是“能不能用”,而是“怎么写才不崩”。
容易踩的坑:忘记结尾重置、在非终端环境(比如重定向到文件)里输出乱码、用错颜色码范围。
- 基础格式是
\033[<em>code</em>m,例如\033[32m是绿色文字,\033[0m必须成对出现来恢复默认 - 推荐用宏或 inline 函数封装,避免手写一堆
\033:比如#define RED "\033[31m",但注意宏不能用于std::format或fmt::format等编译期解析场景 - 如果程序可能被重定向(如
./a.out > out.txt),应检测isatty(STDOUT_FILENO)再决定是否输出颜色,否则日志里全是\033[33m这种不可读字符
跨平台方案别硬套预处理器宏
想写一次代码跑两边,很多人第一反应是 #ifdef _WIN32,但这会让逻辑分散、难维护。更稳的做法是抽象一层小函数,内部按平台分发。
问题不在“能不能判断平台”,而在“要不要把平台差异暴露到业务层”。比如日志模块里每条 LOG_INFO 都去判断 Windows/Linux,不如统一走一个 print_colored 接口。
- 不要在每个
std::cout前加#ifdef,而应封装成类似colored_text("error", Color::Red)的函数 - Windows 上若未启用虚拟终端,ANSI 会被忽略;Linux 上调用
SetConsoleTextAttribute会失败——所以运行时检测比编译时判断更可靠 - C++23 的
std::osyncstream和颜色无关,别指望它解决跨平台输出问题;第三方库如termcolor可用,但引入依赖前先确认它是否真处理了 Windows 旧版 cmd 的兼容性
颜色失效时先查终端能力和输出目标
颜色没反应?90% 不是代码写错,而是环境没满足前提条件。
尤其要注意:Windows 的 CMD 和 PowerShell 行为不同;WSL 默认是 Linux 行为,但宿主机是 Windows;CI 环境(如 GitHub Actions)通常禁用颜色输出。
- 用
echo $TERM(Linux/macOS)或ver+ 查看属性(Windows)确认终端类型;PowerShell 7+ 默认支持 ANSI,老版 CMD 不支持 - 在 IDE 内置终端(如 VS Code、CLion)中测试时,有些会截断或过滤转义序列,建议先用系统原生命令行验证
- 某些 Windows 远程桌面或老旧终端模拟器根本不识别 256 色扩展(如
\033[38;5;123m),坚持用基础 16 色更稳妥
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











