唯一可靠方式是预处理器宏条件编译,因sizeof(void*)用于if会导致未定义行为或链接失败;应使用_win64、__x86_64__等宏实现编译期分叉,确保代码隔离。

编译时就能确定的位数,不该等到运行时去查——C++里判断目标平台是32位还是64位,唯一可靠、无副作用的方式是用预处理器宏做条件编译,sizeof(void*)只能作为辅助验证,不能直接用于if分支。
为什么不能用 if (sizeof(void*) == 8) 做运行时判断
因为sizeof是编译期常量表达式,写成if语句后,两边代码块仍会被完整编译。一旦某一分支引用了只在64位才声明的类型(比如uint64_t)或符号(如__m128i),就会在32位构建中报错,哪怕逻辑上根本不会执行到那里。
- 错误现象:
error: 'uint64_t' was not declared in this scope或undefined reference to 'xxx_64bit_only_function' - 正确做法:必须用
#if/#elif等预处理指令,让编译器彻底跳过不匹配平台的代码段 - 注意:
sizeof(void*)本身没问题,但把它塞进if里就等于放弃编译期隔离能力
Windows 下优先用 _WIN64 和 _WIN32
MSVC 和 clang-cl 都保证这两个宏在 Windows 平台下稳定可用:_WIN32在所有 Windows 构建中都定义(含64位),_WIN64仅在目标为 x64 或 ARM64 时定义。这是最干净、无歧义的判断路径。
- 典型组合:
#if defined(_WIN64)→ 64位 Windows;#elif defined(_WIN32)→ 32位 Windows - 不要单独依赖
_WIN32来判断“是否是32位”,因为它在64位 Windows 上也存在 - 交叉编译场景下(比如在x64机器上用
cl.exe /target:arm64),这些宏反映的是目标平台,不是宿主机
Linux/macOS 下看架构宏:__x86_64__、__aarch64__、__i386__
GCC/Clang 在不同目标架构下会定义标准架构宏,比sizeof(void*)更早、更明确。它们不依赖 ABI 约定,也不受-m32/-m64以外的编译选项干扰。
-
__x86_64__或__amd64__:x86-64 64位 -
__i386__或__i686__:x86 32位 -
__aarch64__:ARM64(如 Apple Silicon、Linux ARM64) -
__arm__且未定义__aarch64__:ARM32(已基本淘汰,但嵌入式仍有) - 避免混用:
__x86_64__和_WIN64互不兼容,Windows 下不要指望前者被定义
sizeof(void*) 只适合编译期断言或日志输出
它确实能告诉你当前翻译单元的目标指针宽度,但仅限于“你知道自己要干什么”的上下文。比如调试打印、静态断言、或生成平台适配的模板特化。
- 安全用法示例:
static_assert(sizeof(void*) == 8, "Only 64-bit targets supported"); - 日志输出:
std::cout - 危险用法:
if (sizeof(void*) == 8) { use_64bit_api(); }—— 这会导致32位构建失败,即使函数体里没调用任何64位专属符号 - 嵌入式边缘情况:AVR、MSP430 等平台
sizeof(void*)可能是2或3,此时“32/64位”概念本身就不适用,别强行套用
真正容易被忽略的是:预处理器宏和sizeof反映的都是**目标平台**,不是运行时系统。如果你真需要检测宿主机 OS 位数(比如打包脚本判断能否运行某二进制),那已经超出了 C++ 标准范畴,得调用GetNativeSystemInfo(Windows)或读取/proc/sys/kernel/osrelease(Linux),但那种需求极少出现在纯 C++ 应用逻辑里。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











