最可靠方式是用预定义宏:_WIN32判Windows(含64位),__linux__判Linux,__APPLE__判macOS;避免WIN32、__unix__等不可靠宏;需按优先级顺序判断,且不可用sizeof(void*)替代系统判断。

用 _WIN32 和 __linux__ 判断 Windows/Linux 最可靠
直接靠预定义宏是最轻量、最跨平台的方式,不需要运行时调用系统 API,编译期就能分流。C++ 标准不规定这些宏,但所有主流编译器(MSVC、GCC、Clang)都支持一组事实标准:
-
_WIN32:Windows 平台必定义(32 位和 64 位都定义,_WIN64可选) -
__linux__:Linux 内核系统(GCC/Clang 默认定义;MSVC 不定义) -
__APPLE__+__MACH__:macOS(常一起出现,单用__APPLE__更稳妥) -
__FreeBSD__、__OpenBSD__等:对应 BSD 系统
别用 WIN32(旧版 MSVC 曾用,但不可靠)、也别依赖 __unix__(某些嵌入式或非 POSIX Unix 可能不定义,且 Windows Subsystem for Linux 也会定义它,造成误判)。
#ifdef _WIN32 要配 #else 还是 #elif defined(__linux__)?
取决于你是否需要显式区分 Linux 和其他非 Windows 系统(比如 macOS)。如果只关心「Windows vs 非 Windows」,#ifdef _WIN32 + #else 就够用;但如果要为 Linux 单独写逻辑(比如用 epoll),就得明确判断:
#ifdef _WIN32
// Windows 特有代码,如 CreateFile, Winsock
#elif defined(__linux__)
// Linux 特有代码,如 epoll_wait, inotify
#elif defined(__APPLE__)
// macOS 特有代码,如 kqueue, launchd
#else
// 兜底:其他 Unix-like(FreeBSD、Solaris 等)
#endif
注意顺序:_WIN32 必须放最前——因为某些 MinGW 环境下,__linux__ 不定义,但 __unix__ 可能被误设,而 _WIN32 是 Windows 的唯一强信号。
立即学习“C++免费学习笔记(深入)”;
为什么不能用 sizeof(void*) == 8 判断 64 位系统?
这是常见误区:指针大小只反映当前编译目标架构,和操作系统类型无关。例如:
- x86_64 Windows 下
sizeof(void*)是 8,但它是 Windows - ARM64 Linux 下也是 8,但它是 Linux
- 即使在 Linux 上用
-m32编译,sizeof(void*)会变成 4,但系统仍是 Linux
所以它只能辅助判断位数,不能替代 OS 宏。真正需要区分系统行为(如路径分隔符、线程创建方式、文件权限模型)时,必须用 OS 宏,而不是架构宏(如 __x86_64__ 或 __aarch64__)。
跨平台头文件路径和系统 API 包含怎么写?
头文件本身不跨平台,得按 OS 条件包含:
#ifdef _WIN32
#include
#include
#else
#include
#include
#include
#endif
实际使用中容易漏掉两点:
- Windows 下需在
winsock2.h前避免包含windows.h(否则可能因宏冲突导致编译失败),或用#define WIN32_LEAN_AND_MEAN预先抑制 - Linux/macOS 下某些函数(如
getaddrinfo)需要定义_POSIX_C_SOURCE或_GNU_SOURCE才可见,这类宏必须在任何头文件之前定义
宏判断看似简单,但一旦混入构建系统(CMake)、交叉编译或容器环境(如 alpine Linux 用 musl libc),就容易因编译器差异或宏污染出问题——最稳的做法是:只用编译器原生提供的宏,不自定义中间宏做二次封装。










