正如标题所说,是否有任何优雅且安全的方法来确定架构是 32 位还是 64 位。通过优雅,您可以想到精确、正确、简短、干净和聪明的方式。所谓安全,就是从标准、C89/C99、操作系统独立性的角度来考虑安全。
7 回答
简短的回答:没有
长答案:这取决于太多的操作系统/编译器组合。例如在运行时,在 linux 上您可以查询 proc 文件系统,而在 windows 上您可以查询寄存器。
您可以使用以下内容证明用于编译的编译器具有 32/64 位目标:
bool is_32bit() {
return sizeof(int *) == 4;
}
bool is_64bit() {
return sizeof(int *) == 8;
}
这可以在一些假设下工作(例如它在运行时工作)。您可以为您的平台搜索编译时#define
,但这是众所周知的混乱。
如果您使用的是 GCC(如标签中所示),您可以进行测试,作为编译时测试
#if __SIZEOF_POINTER__ == 8
确定它是否是 64 位系统。确保您使用的 GCC 版本在使用__SIZEOF_POINTER__
之前完全定义。
指针的大小并不是一个真正值得测试的好东西——在标准 C 语言中,无论如何您都无法使用该测试的结果来做任何事情。
我的建议是 test ((size_t)-1)
,这是 C 理解的最大对象大小:
if ((size_t)-1 > 0xffffffffUL)
{
printf("> 32 bits\n");
}
else
{
printf("<= 32 bits\n");
}
如果它大于0xffffffffUL
那么您原则上可以拥有大于2**32 - 1
字节的对象,这似乎比模糊的“32 位与 64 位”更有意义。
(例如,如果您知道 的最大值size_t
仅为2**32 - 1
,那么尝试mmap()
大于 1 或 2 GB 的区域是没有意义的。)
最常见的方法是测试sizeof(void*)
和sizeof(int)
(注意它们不一定必须相同)。
x86/x64 CPU 上的另一种可能性是测试“lm”标志。如果它存在,则 CPU 理解 AMD64 指令集。
不幸的是,安全和便携的技术是不可能的(因为安全和便携只允许您使用 C 标准中的规则)。
sizeof(int)
使用一些更常见的编译器可能会为您提供 4 个 32 位平台和 8 个 64 位平台,但这不能保证。所有 C 标准都说 int 应该是目标上计算的“自然”大小,即使在 64 位世界中,许多编译器也将 sizeof(int) 保留为 4,理由是它“足够” .
sizeof(void*)
更好,因为指针必须具有适当的大小才能寻址整个地址空间。sizeof(void*)
因此可能会酌情给您 4 或 8。但是从技术上讲,即使这样也不能保证,因为 sizeof 可以为您提供存储某些内容所需的字节数,并且一个字节不必是 8 位。字节在技术上是最小的可寻址内存单元,在人们习惯的大多数平台上恰好是 8 位。8 位可寻址非常常见,但我使用的是 16 位可寻址和 16 位字长(sizeof(int)
1 也是)的芯片。因此,如果您的字节大小不是 8 位,那么sizeof(void*)
可以为您提供各种值。
另一方面,如果您只是想区分 x86 和 x64(32 位和 64 位 PC 处理器),那么 sizeof(void*) 就足够了,并且可以跨编译器移植。
代码库上的 32 位或数据库上的 32 位。:-) 8086 处理器具有 16 位数据和 20 位代码存储器。此外,现代哈佛机器通过代码/数据分离做一些奇怪的事情......
您可以查看cpuid
x86 处理器的说明。其他处理器系列可能没有这样的指令...YMMV。
int iedx;
__asm
{
mov eax, 0x80000001;
cpuid;
mov, iedx,edx;
}
if (iedx & (1 << 29))
{
return 1;
}
return 0;