CPU 寄存器的大小

size of CPU register

通常最好使用 CPU 寄存器的全部容量。 对于可移植的代码,这意味着在 64 位 CPU 上使用 64 位运算和存储,而在 32 位 CPU 上仅使用 32 位(否则,将模拟 64 位指令在 32 位模式下,导致毁灭性的性能)。

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

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

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

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

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

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

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

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

Each of the following types designates an integer type that is usually fastest to operate with among all integer types that have at least the specified width.

带脚注:

The designated type is not guaranteed to be fastest for all purposes; if the implementation has no clear grounds for choosing one type over another, it will simply pick some integer type satisfying the signedness and width requirements.

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

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

更好的起点

快速实验表明,如果我用 gcc -mx32 编译,uint_fast16_tuint_fast32_t 都是 32 位。在没有 -mx32 的情况下编译时它们都是 64 位的(在我的 x86_64 系统上)。这意味着,至少对于 gcc,uint_fastN_t 类型 不会 做你想做的事。您将需要 x32 的特殊情况代码。 (可以说 gcc 应该 在 x32 模式下为 uint_fastN_t 使用 64 位类型。我只是 posted this question 问了这个问题。)

This question asks how to detect an x32 environment in the preprocessor. gcc provides no direct way to determine this, but I've just posted an answer 建议使用 __x86_64__SIZE_MAX 宏。