应使用预定义宏 _WIN32 和 __linux__ 判断系统:Windows 编译器(MSVC/Clang/GCC)均定义 _WIN32,Linux 工具链定义 __linux__;二者互斥,macOS 均不定义,需用 __APPLE__ 单独判断。

用预定义宏判断 Windows 或 Linux
直接看 _WIN32 和 __linux__ 这两个宏,它们由编译器自动定义,不需要额外头文件或链接选项。
Windows 下 MSVC、Clang、GCC 都定义 _WIN32(注意:64 位 Windows 也定义它,_WIN64 可选但不必要);Linux 下 GCC/Clang 默认定义 __linux__(注意双下划线,不是 linux 或 LINUX)。
-
_WIN32在 MinGW、MSVC、Clang for Windows 上都可靠;别用WIN32(CMake 常用,但编译器不定义) -
__linux__是 GNU 工具链事实标准;__unix__范围太宽(macOS 也定义它),不能单独用来判 Linux - macOS 不匹配这两个宏,如果需要区分,得加
__APPLE__分支
跨平台代码里怎么写条件编译分支
用 #ifdef / #elif / #else 组合,顺序建议先 Win 再 Linux,最后 fallback(比如 macOS 或未知系统)。
别嵌套过深,一个判断层级足够;避免用 #if defined(WIN32) || defined(_WIN32) 这种冗余写法——_WIN32 就够了。
立即学习“C++免费学习笔记(深入)”;
#ifdef _WIN32
const char* sep = "\";
HANDLE h = CreateFile(...);
#elif defined(__linux__)
const char* sep = "/";
int fd = open(...);
#else
#error "Unsupported OS"
#endif常见错误:宏没生效或误判
最常踩的坑是编译环境和预期不一致:比如在 WSL 里用 Windows 的 VS Code 远程编译,却忘了实际跑的是 Linux 工具链,结果 _WIN32 没定义。
- 用
g++ -dM -E - < /dev/null | grep -i linux快速查当前编译器定义了哪些宏 - Clang on Windows(如 clang-cl)可能同时定义
_WIN32和__linux__?不会——clang-cl 模仿 MSVC 行为,只定义_WIN32 - 自己用
-D__linux__强制定义?危险。这会让 Linux 头文件跳过初始化逻辑,或触发 glibc 内部条件编译错误
为什么不用运行时检测(比如调用 uname())
宏判定是编译期行为,零开销、无依赖、确定性强;而运行时检测要引入系统调用、头文件(<sys/utsname.h>)、链接依赖,还可能失败(权限、容器限制)。
除非你写的是可移植二进制(一份程序跑多个系统),否则编译期分发更干净。真要运行时判断,uname() 返回的 sysname 字段才可靠,getenv("OS") 在 Linux 下根本不存在。
宏不是万能的,但它在绝大多数 C++ 构建场景里就是事实标准——只要构建环境明确,就别绕弯子。










