应优先使用编译器预定义宏\_WIN32、\_\_linux\_\_、\_\_APPLE\_\_判断平台,注意\_\_ANDROID\_\_需在\_\_linux\_\_前判断,iOS/macOS需配合\<TargetConditionals.h\>中的TARGET\_OS\_IPHONE/TARGET\_OS\_MAC区分,避免依赖\_\_unix\_\_或错误拼写,并按编译器(Clang/GCC/MSVC)而非仅\_\_GNUC\_\_做特化处理。

直接用预定义宏判断,别自己造宏;优先选 _WIN32、__linux__、__APPLE__ 这三个,覆盖 Windows/Linux/macOS 主流场景。
怎么写平台判断才可靠
编译器自动定义的宏才是可信依据,手动加 -DPLATFORM_LINUX 等自定义宏容易漏配或冲突。实际开发中应以编译器原生宏为准:
-
_WIN32在所有 Windows(32/64 位)下都定义,MSVC、MinGW、Clang on Windows 全支持,比_WIN64更通用 -
__linux__是 GCC/Clang 在 Linux 下的标准宏,注意不是linux或LINUX(后者常见于错误拼写) -
__APPLE__在 macOS 和 iOS 上都定义,但仅靠它无法区分 macOS 和 iOS —— 需配合TARGET_OS_MAC或TARGET_OS_IPHONE(需包含<TargetConditionals.h>) - 避免用
__unix__单独判断 Linux:它在 macOS、FreeBSD、Solaris 下也都定义,误判风险高
Clang 伪装 GCC 导致的陷阱
Clang 默认定义 __GNUC__(值为 4),这让很多只检查 __GNUC__ 的代码误认为是 GCC,结果在 Clang 下编译失败。典型问题:
- 调用 GCC 特有扩展如
__attribute__((optimize("O3"))),Clang 可能不支持或行为不同 - 依赖
__GNUC_MINOR__做版本分支,Clang 返回的值无实际意义 - 用
#ifdef __GNUC__包裹 POSIX 头文件(如<sys/stat.h>),却在 macOS 上漏掉__APPLE__分支,导致头文件缺失
正确做法是:先判编译器,再按需细分。例如:
立即学习“C++免费学习笔记(深入)”;
#if defined(__clang__)
// Clang-specific
#elif defined(__GNUC__)
// 真正的 GCC(非 Clang)
#elif defined(_MSC_VER)
// MSVC
#endif
Android 和 iOS 要单独处理
Android 和 iOS 都是 Unix-like 系统,但它们的宏不能靠 __linux__ 或 __APPLE__ 一概而论:
- Android 定义
__ANDROID__,但它也定义__linux__—— 所以必须把__ANDROID__放在__linux__之前判断,否则会被后者“吞掉” - iOS 不定义
__linux__,但定义__APPLE__;需引入<TargetConditionals.h>后用TARGET_OS_IPHONE确认 - macOS 上
TARGET_OS_MAC为 1,iOS 上为 0;不引入该头文件直接用会报错
示例顺序:
#ifdef __ANDROID__
// Android-only code
#elif defined(__linux__)
// 其他 Linux(桌面、服务器等)
#elif defined(__APPLE__) && TARGET_OS_IPHONE
// iOS
#elif defined(__APPLE__) && TARGET_OS_MAC
// macOS
#elif defined(_WIN32)
// Windows
#endif
别在头文件里裸写 #ifdef 块
跨平台头文件里直接塞大段条件编译,会导致可读性崩坏、IDE 补全失效、静态分析工具误报。更稳妥的做法:
- 把平台差异收敛到极小接口层,比如统一声明
platform_sleep_ms(int ms),各平台实现放在独立.cpp文件里 - 用 CMake 控制源文件列表:在
CMakeLists.txt中根据WIN32、APPLE、UNIX变量选择不同实现文件,而非在头里硬分支 - 若必须在头里条件编译,用
#if defined(...)替代嵌套#ifdef,便于逻辑组合(如#if defined(__linux__) && !defined(__ANDROID__))
真正难的不是写对一个 #ifdef,而是保证所有平台路径都被显式覆盖且互斥 —— 漏掉一个分支,CI 就可能在某台机器上静默失败。


















