5

正如标题所说,是否有任何优雅且安全的方法来确定架构是 32 位还是 64 位。通过优雅,您可以想到精确、正确、简短、干净和聪明的方式。所谓安全,就是从标准、C89/C99、操作系统独立性的角度来考虑安全。

4

7 回答 7

9

简短的回答:没有

长答案:这取决于太多的操作系统/编译器组合。例如在运行时,在 linux 上您可以查询 proc 文件系统,而在 windows 上您可以查询寄存器。

您可以使用以下内容证明用于编译的编译器具有 32/64 位目标:

bool is_32bit() {
    return sizeof(int *) == 4;
} 

bool is_64bit() {
    return sizeof(int *) == 8;
} 

这可以在一些假设下工作(例如它在运行时工作)。您可以为您的平台搜索编译时#define,但这是众所周知的混乱。

于 2009-08-17T14:24:59.073 回答
8

如果您使用的是 GCC(如标签中所示),您可以进行测试,作为编译时测试

#if __SIZEOF_POINTER__ == 8

确定它是否是 64 位系统。确保您使用的 GCC 版本在使用__SIZEOF_POINTER__之前完全定义。

于 2009-08-17T14:26:55.403 回答
3

指针的大小并不是一个真正值得测试的好东西——在标准 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 的区域是没有意义的。)

于 2009-08-17T22:10:21.570 回答
2

最常见的方法是测试sizeof(void*)sizeof(int)(注意它们不一定必须相同)。

x86/x64 CPU 上的另一种可能性是测试“lm”标志。如果它存在,则 CPU 理解 AMD64 指令集。

于 2009-08-17T14:20:27.503 回答
2

不幸的是,安全和便携的技术是不可能的(因为安全和便携只允许您使用 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*) 就足够了,并且可以跨编译器移植。

于 2009-08-17T15:56:22.183 回答
1

代码库上的 32 位或数据库上的 32 位。:-) 8086 处理器具有 16 位数据和 20 位代码存储器。此外,现代哈佛机器通过代码/数据分离做一些奇怪的事情......

您可以查看cpuidx86 处理器的说明。其他处理器系列可能没有这样的指令...YMMV。

于 2009-08-17T22:34:57.777 回答
1
int iedx;

__asm
{

mov eax, 0x80000001;
cpuid;
mov, iedx,edx;
}

     if (iedx & (1 << 29))
       {
        return 1;
       }
     return 0;
于 2009-10-24T17:32:20.327 回答