我想要128位整数,因为我想存储两个64位数的乘法结果。在gcc 4.4及以上版本中有没有这样的东西?
答案 0 :(得分:30)
啊,大整数不是C的强项。
GCC确实有unsigned __int128
/ __int128
类型,从版本4.something开始(这里不确定)。然而,我似乎记得在此之前有__int128_t
def。
这些仅适用于64位目标。
(编者注:这个答案曾经声称gcc定义了uint128_t
和int128_t
。我在Godbolt编译器资源管理器上测试的所有版本都没有定义那些没有前导__
的类型, gcc4.1到8.2,或clang或ICC。)
答案 1 :(得分:11)
您可以使用处理任意或大精度值的库,例如GNU MP Bignum Library。
答案 2 :(得分:10)
128位整数类型仅在64位目标上可用,因此,即使您已经检测到最新的GCC版本,也需要检查其可用性。理论上,gcc 可以在需要4个32位寄存器来保存一个寄存器的机器上支持TImode整数,但是我认为在任何情况下它都不会。
GCC 4.6及更高版本具有__int128
/ unsigned __int128
定义为内置类型。使用
#ifdef __SIZEOF_INT128__
进行检测。
GCC 4.1及更高版本在__int128_t
中定义了__uint128_t
和<stdint.h>
。在最新的编译器上,这可能是根据__int128
定义的。 (如果要使用#include <stdint.h>
而不是__int128_t
,则仍然需要__int128
。)
我测试了on the Godbolt compiler explorer的第一个编译器版本,以支持这3种功能(在x86-64上)。 Godbolt只返回到gcc4.1,ICC13和clang3.0,因此我用<= 4.1表示实际的第一个支持可能更早了。
legacy recommended(?) | One way of detecting support
__uint128_t | [unsigned] __int128 | #ifdef __SIZEOF_INT128__
gcc <= 4.1 | 4.6 | 4.6
clang <= 3.0 | 3.1 | 3.3
ICC <= 13 | <= 13 | 16. (Godbolt doesn't have 14 or 15)
如果您为32位体系结构(例如ARM或带有-m32
的x86)进行编译,则即使是这些编译器中的任何最新版本,也都不支持128位整数类型。因此,如果您的代码在没有它的情况下完全可以工作,那么您需要在使用之前先进行检测。
我知道唯一可以检测到的直接CPP宏是__SIZEOF_INT128__
,但是不幸的是,一些旧的编译器版本在不定义它的情况下支持它。 (并且__uint128_t
没有宏,只有gcc4.6样式unsigned __int128
)。 How to know if __uint128_t is defined
某些人仍在使用RHEL(RedHat Enterprise Linux)上的gcc4.4等古老的编译器版本,或类似的老旧系统。如果您关心这样的过时gcc版本,则可能要坚持使用__uint128_t
。也许可以根据sizeof(int_fast32_t)
来检测64位,这出于某些原因在某些64位ISA上为8。但不是在x32或ILP32 AArch64之类的ILP32 ISA上,因此,如果未定义sizeof(void*)
,只需检查__SIZEOF_INT128__
。
可能有些gcc没有定义__int128
的64位ISA,甚至有些gcc 确实定义__int128
的32位ISA,但是我'什么都不知道。
正如对另一个答案的评论所指出的那样,GCC内部是整数TI模式。 (四整数= int
的4倍宽度,而DImode =双倍宽度,而SImode =普通int
。)与the GCC manual points out一样,支持__int128
的目标也受支持128位整数模式(TImode)。
typedef unsigned uint128_t __attribute__ ((mode (TI)));
随机事实:ICC19 -E -dM
定义:
#define __GLIBCXX_TYPE_INT_N_0 __int128
#define __GLIBCXX_BITSIZE_INT_N_0 128
测试功能为:
#include <stdint.h>
#define uint128_t __uint128_t
//#define uint128_t unsigned __int128
uint128_t mul64(uint64_t a, uint64_t b) {
return (uint128_t)a * b;
}
所有支持它的编译器都可以高效地对其进行编译,以
mov rax, rdi
mul rsi
ret # return in RDX:RAX