最可靠方式是用 sizeof(void) 配合预定义宏组合判断:_win32 和 linux 仅标识操作系统平台,不区分位数;_win64、__x86_64__ 等宏可辅助识别架构,但 sizeof(void)==8 才真正反映目标平台指针宽度,且为编译期常量,跨平台通用。

直接看结论:用 sizeof(void*) 配合预定义宏最可靠,_WIN32 和 __linux__ 本身不区分位数,别被名字骗了。
为什么不能只靠 _WIN32 或 __linux__?
这些宏只表示操作系统平台,和位数无关。比如 Windows 上的 64 位程序仍会定义 _WIN32(微软明确要求),Linux 的 64 位内核也照样定义 __linux__。光靠它们判断位数,必然出错。
常见错误现象:
在 x86_64 Windows 上编译时误以为是 32 位,导致指针截断、结构体对齐异常、size_t 与 int 混用崩溃。
-
_WIN32→ 表示 Windows 平台(32 或 64 位都定义) -
_WIN64→ 仅 64 位 Windows 编译器定义(MSVC、Clang/LLVM on Windows) -
__x86_64__/__aarch64__→ CPU 架构宏,较可靠但非绝对(交叉编译可能失真) -
sizeof(void*) == 8→ 编译期常量,最贴近实际运行模型
推荐写法:用 sizeof(void*) + 标准宏组合判定
这是跨平台、编译器无关、且语义最清晰的方式。C++11 起 sizeof 是常量表达式,可直接用于 #if。
#if sizeof(void*) == 8
// 64-bit target
using size_alias = uint64_t;
#elif sizeof(void*) == 4
// 32-bit target
using size_alias = uint32_t;
#else
#error "Unsupported pointer size"
#endif
注意:
• 不要用 sizeof(int) —— 它在多数 64 位系统上仍是 4 字节;
• sizeof(long) 在 Windows(LLP64)和 Linux(LP64)下行为不一致,不可靠;
• Clang/GCC/MSVC 全支持 sizeof(void*) 在预处理中使用(GCC ≥ 4.3,Clang ≥ 2.9,MSVC ≥ 2015)。
各编译器实际可用的位数相关宏
虽然不建议单独依赖,但了解它们有助于调试或兼容旧代码:
- MSVC:
_WIN64(64 位)、_M_X64(x64)、_M_ARM64(ARM64) - GCC/Clang:
__x86_64__、__aarch64__、__LP64__(表示 long 和 pointer 为 64 位,Linux/macOS 64 位成立,Windows 不成立) - POSIX 系统可查:
__SIZEOF_POINTER__(GCC/Clang 提供,值为 4 或 8)
⚠️ 小心 __LP64__:它在 Windows x64 下不定义,但在 macOS/Linux x64 下定义 —— 如果你写 #ifdef __LP64__ 就漏掉 Windows 64 位了。
实际项目中该选哪一种?
优先级从高到低:
- 需要精确控制内存布局或 ABI(如序列化、插件接口)→ 用
sizeof(void*)判定,辅以static_assert校验 - 只需区分整数宽度(如选
intptr_t)→ 直接用intptr_t,标准已保证其与指针等宽 - 做平台适配(如调用不同 DLL/so)→ 结合
_WIN32+_WIN64或__linux__+__x86_64__,但务必验证指针大小
最容易被忽略的一点:交叉编译环境下,宿主机宏(如 uname -m 输出)和目标机宏完全无关,一切必须以目标平台的预定义宏和 sizeof 为准。别在 CMakeLists.txt 里用 HOST_SYSTEM_PROCESSOR 推断目标位数。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











