代码之家  ›  专栏  ›  技术社区  ›  mtasic85 Ed Heal

确定体系结构是32位还是64位的优雅而安全的方法

  •  5
  • mtasic85 Ed Heal  · 技术社区  · 17 年前

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

    7 回复  |  直到 9 年前
        1
  •  3
  •   caf    17 年前

    指针的大小对于测试来说并不是一件好事——在标准C中,您无论如何都不能对测试结果做太多的工作。

    我的建议是测试 ((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的区域。)

        2
  •  9
  •   dfa    17 年前

    简短回答: 不

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

    您可以证明用于编译的编译器有一个32/64位的目标,其使用如下所示:

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

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

        3
  •  8
  •   Martin v. Löwis    17 年前

    如果您使用gcc(如标记中所示),那么可以测试,作为编译时测试。

    #if __SIZEOF_POINTER__ == 8
    

    以了解它是否是64位系统。确保使用的gcc版本定义 __SIZEOF_POINTER__ 在使用它之前。

        4
  •  2
  •   ypnos    17 年前

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

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

        5
  •  2
  •   WillW    17 年前

    不幸的是,安全和可移植的技术是不可能的(因为安全和可移植只允许您使用C标准中的规则)。

    sizeof(int) 对于一些更常见的编译器,32位平台可以提供4个编译器,64位平台可以提供8个编译器,但这并不能保证。 所有的C标准都说int应该是针对目标计算的“自然”大小,而且许多编译器甚至在64位的世界中都将sizeof(int)保留为4,理由是它“足够”。

    sizeof(void*) 更好的方法是,指针的大小必须合适,才能寻址整个地址空间。 SIZEOF(空洞*) 因此,可能会酌情给你4或8分。 不过,从技术上讲,即使这样也不能保证,因为sizeof提供了存储某些内容所需的字节数,而且一个字节不必是8位。从技术上讲,字节是最小的可寻址内存单元,在大多数人们习惯的平台上恰好是8位。8位可寻址是非常常见的,但是我使用的芯片是16位可寻址和16位字大小(所以 SIEZOF(INT) 是1)。 所以,如果您的字节大小不是8位,那么 SIZEOF(空洞*) 可以给你各种价值观。

    另一方面,如果您只是想区分x86和x64(32位和64位PC处理器),那么sizeof(void*)就足够了,可以跨编译器进行移植。

        6
  •  1
  •   Paul Nathan    17 年前

    代码库中的32位或数据库中的32位。:-)8086处理器具有16位数据和20位代码存储器。而且,现代哈瓦德机器用代码/数据分离做一些奇怪的事情…

    你可以查一下 cpuid x86处理器说明。其他处理器系列可能没有这样的指令…ymmv。

        7
  •  1
  •   Mandrake    16 年前
    int iedx;
    
    __asm
    {
    
    mov eax, 0x80000001;
    cpuid;
    mov, iedx,edx;
    }
    
         if (iedx & (1 << 29))
           {
            return 1;
           }
         return 0;