CPU寄存器的大小

Cya*_*yan 13 c cpu-registers

通常最好将CPU寄存器用于其全部容量.对于便携式代码,它意味着在64位CPU上使用64位算术和存储,在32位CPU上仅使用32位(否则,将在32位模式下模拟64位指令,从而导致毁灭性的表演).

这意味着有必要检测CPU寄存器的大小,通常是在编译时(因为运行时测试很昂贵).

多年来,我一直使用简单的启发式方法sizeof(nativeRegisters) == sizeof(size_t).

它在许多平台上运行良好,但它似乎是linux x32的错误启发式:在这种情况下,size_t只有32位,而寄存器仍然可以处理64位.它会导致一些性能损失(对我的用例来说很重要).

即使在这种情况下,我也想正确检测CPU寄存器的可用大小.

我怀疑我可以尝试在特殊情况x32模式下找到一些特定于编译器的宏.但我想知道是否存在更通用的东西,以涵盖更多情况.例如,另一个目标是OpenVMS 64位:那里,本机寄存器大小是64位,但size_t只是32位.

Kei*_*son 6

没有可靠且可移植的方法来从C确定寄存器大小.C甚至没有"寄存器"的概念(register关键字的描述没有提到CPU寄存器).

但它确实定义了一组整数类型,它们是至少指定大小的最快类型.<stdint.h>定义uint_fastN_t,对于N = 8,16,32,64.

如果您假设寄存器至少为32位,则uint_fast32_t可能与寄存器的大小相同,无论是32位还是64位.这不保证.这是标准所说的:

以下每种类型都指定一个整数类型,该类型通常在具有至少指定宽度的所有整数类型中运行最快.

用脚注:

指定类型不能保证最快用于所有目的; 如果实现没有明确的理由选择一种类型而不是另一种类型,它将简单地选择一些满足符号和宽度要求的整数类型.

事实上,我建议使用[u]int_fastN_t类型比尝试匹配CPU寄存器大小更清楚地表达您的意图.

如果这对某些目标不起作用,则需要添加一些特殊情况 #if#ifdef指令来选择合适的类型.但是uint_fast32_t(或者uint_fast16_t如果你想支持16位系统)可能是一个比size_tor 更好的起点int.

快速实验表明,如果我编译gcc -mx32,无论是uint_fast16_tuint_fast32_t是32位.在没有-mx32(在我的x86_64系统上)编译时,它们都是64位.这意味着,至少对于gcc来说,这些uint_fastN_t类型并不能满足您的需求.你需要x32的特例代码.(可以说gcc 应该uint_fastN_t在x32模式下使用64位类型.我刚刚发布了这个问题.)

此问题询问如何在预处理器中检测x32环境.gcc没有提供直接的方法来确定这一点,但我刚刚发布了一个建议使用__x86_64__SIZE_MAX的答案.