如何在C/C++中检测机器字大小?

rus*_*tyx 13 c c++ cpu-registers

是否有一种或多或少可靠的方法(不一定完美)来检测我正在编译的目标体系结构机器字大小

通过机器字大小我的意思是整数累加器寄存器(例如EAX在x86,RAX在x86_64等,尺寸流扩展,段或浮点寄存器).

该标准似乎没有提供"机器字"数据类型.因此,我不是在寻找100%可移植的方式,只适用于大多数常见情况(Intel x86 Pentium +,ARM,MIPS,PPC - 即基于寄存器的现代商品处理器).

size_t并且uintptr_t听起来像是好的候选者(并且在实践中匹配我测试的所有寄存器大小)但当然是其他东西,因此不能保证总是如Is size_t中所描述的那样.

上下文

假设我正在对一块连续数据实现散列循环.将结果散列依赖于编译器是可以的,只有速度很重要.

示例:http://rextester.com/VSANH87912

在Windows上进行测试表明,在64位模式下,64位块的散列更快,在32位模式下散列为32位:

64-bit mode
int64: 55 ms
int32: 111 ms

32-bit mode
int64: 252 ms
int32: 158 ms
Run Code Online (Sandbox Code Playgroud)

Edw*_*ard 12

因为C和C++语言故意抽象出机器字大小这样的考虑因素,所以任何方法都不可能100%可靠.但是,有int_fastXX_t各种类型可以帮助您推断尺寸.例如,这个简单的C++程序:

#include <iostream>
#include <cstdint>

#define SHOW(x) std::cout << # x " = " << x << '\n'

int main()
{
    SHOW(sizeof(int_fast8_t));
    SHOW(sizeof(int_fast16_t));
    SHOW(sizeof(int_fast32_t));
    SHOW(sizeof(int_fast64_t));
}
Run Code Online (Sandbox Code Playgroud)

在我的64位Linux机器上使用gcc版本5.3.1生成此结果:

sizeof(int_fast8_t) = 1
sizeof(int_fast16_t) = 8
sizeof(int_fast32_t) = 8
sizeof(int_fast64_t) = 8
Run Code Online (Sandbox Code Playgroud)

这表明发现寄存器大小的一种方法可能是寻找所需大小(例如,16位值为2个字节)与相应int_fastXX_t大小之间的最大差异,并使用int_fastXX_t作为寄存器大小的大小.

进一步结果

Windows 7,64位机器上的Cygwin下的gcc 4.9.3:与上面相同

Windows 7,64位计算机上的Visual Studio 2013(v 12.0):

sizeof(int_fast8_t) = 1
sizeof(int_fast16_t) = 4
sizeof(int_fast32_t) = 4
sizeof(int_fast64_t) = 8
Run Code Online (Sandbox Code Playgroud)

Linux,gcc 4.6.3在32位ARM和Linux上,gcc 5.3.1在32位Atom上:

sizeof(int_fast8_t) = 1
sizeof(int_fast16_t) = 4
sizeof(int_fast32_t) = 4
sizeof(int_fast64_t) = 8
Run Code Online (Sandbox Code Playgroud)

  • @RobertJacobs:结果完全**是使用哪个编译器的结果,所以它更多的是编译器测试而不是CPU测试. (2认同)

Rob*_*obs 6

我想你想要的

sizeof(size_t)这应该是索引的大小.即.ar[index]

32 bit machine

char 1
int 4
long 4
long long 8
size_t 4
Run Code Online (Sandbox Code Playgroud)

64 bit machine

char 1
int 4
long 8
long long 8
size_t 8
Run Code Online (Sandbox Code Playgroud)

它可能更复杂,因为32位编译器在64位机器上运行.他们的输出32即使机器能够更多.

我在下面添加了windows编译器

Visual Studio 2012 compiled win32

char 1
int 4
long 4
long long 8
size_t 4
Run Code Online (Sandbox Code Playgroud)

Visual Studio 2012 compiled x64

char 1
int 4
long 4
long long 8
size_t 8
Run Code Online (Sandbox Code Playgroud)

  • `size_t`应该"大到足以包含任何对象的字节大小"[support.types]/6.它与数组访问无关. (3认同)
  • @RobertJacobs - 是的,`malloc`采用类型为`size_t`的参数.那是因为`size_t`可以表示任何对象的大小; 这就是标准所要求的,这就是我引用标准的原因.数组索引大约是**指针**范围; 如果你索引到`char`数组,你的索引类型最好足够大,以保持`char`数组的最大大小,即使单个寄存器不足以容纳这样的索引值. (2认同)