C语言 gcc 中有 128 位整数吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16088282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:04:38  来源:igfitidea点击:

Is there a 128 bit integer in gcc?

cgccx86-64bigint128-bit

提问by MetallicPriest

I want a 128 bit integer because I want to store results of multiplication of two 64 bit numbers. Is there any such thing in gcc 4.4 and above?

我想要一个 128 位整数,因为我想存储两个 64 位数字相乘的结果。gcc 4.4 及更高版本中是否有这样的东西?

采纳答案by Peter Cordes

A 128-bit integer type is only ever available on 64-bit targets, so you need to check for availability even if you have already detected a recent GCC version. In theory gcc couldsupport TImode integers on machines where it would take 4x 32-bit registers to hold one, but I don't think there are any cases where it does.

128 位整数类型仅在 64 位目标上可用,因此即使您已经检测到最近的 GCC 版本,您也需要检查可用性。理论上,gcc可以在需要 4 个 32 位寄存器来保存一个的机器上支持 TImode 整数,但我认为在任何情况下都不会。



GCC 4.6 and later has a __int128/ unsigned __int128defined as a built-in type.Use
#ifdef __SIZEOF_INT128__to detect it.

GCC 4.6 及更高版本将__int128/unsigned __int128定义为内置类型。使用
#ifdef __SIZEOF_INT128__检测到它。

GCC 4.1 and later define __int128_tand __uint128_tas built-in types. (You don't need #include <stdint.h>for these, either. Proof on Godbolt.)

GCC 4.1 及更高版本将__int128_t和定义__uint128_t为内置类型。(你也不需要#include <stdint.h>这些。Godbolt 的证明。)

I tested on the Godbolt compiler explorerfor the first versions of compilers to support each of these 3 things (on x86-64). Godbolt only goes back to gcc4.1, ICC13, and clang3.0, so I've used <= 4.1 to indicate that the actual first support might have been even earlier.

在 Godbolt 编译器资源管理器上测试了第一个版本的编译器,以支持这 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)

If you compile for a 32-bit architecture like ARM, or x86 with -m32, no 128-bit integer type is supported with even the newest version of any of these compilers.So you needto detect support before using, if it's possible for your code to work at all without it.

如果您针对 ARM 或 x86 等 32 位体系结构进行编译,-m32则即使这些编译器的最新版本也不支持 128 位整数类型。因此,您需要在使用前检测支持,如果您的代码在没有它的情况下也能工作。

The only direct CPP macro I'm aware of for detecting it is __SIZEOF_INT128__, but unfortunately some old compiler versions support it without defining it. (And there's no macro for __uint128_t, only the gcc4.6 style unsigned __int128). How to know if __uint128_t is defined

我所知道的用于检测它的唯一直接 CPP 宏是__SIZEOF_INT128__,但不幸的是,一些旧的编译器版本支持它而没有定义它。(并且没有宏__uint128_t,只有 gcc4.6 样式unsigned __int128)。 如何知道 __uint128_t 是否已定义

Some people still use ancient compiler versions like gcc4.4 on RHEL (RedHat Enterprise Linux), or similar crusty old systems. If you care about obsolete gcc versions like that, you probably want to stick to __uint128_t. And maybe detect 64-bitness in terms of sizeof(void*) == 8as a fallback for __SIZEOF_INT128__no being defined. (I think GNU systems always have CHAR_BIT==8). That will give a false negative on ILP32 ABIs on 64-bit ISAs (like x86-64 Linux x32, or AArch64 ILP32), but this is already just a fallback / bonus for people using old compilers that don't define __SIZEOF_INT128__.

有些人仍然在 RHEL(RedHat Enterprise Linux)上使用像 gcc4.4 这样的古老编译器版本,或者类似的老旧系统。如果你关心这样过时的 gcc 版本,你可能想坚持使用__uint128_t. 并且可能检测 64 位sizeof(void*) == 8作为__SIZEOF_INT128__未定义的回退。(我认为 GNU 系统总是有CHAR_BIT==8)。这将对 64 位 ISA(如 x86-64 Linux x32 或 AArch64 ILP32)上的 ILP32 ABI 产生假否定,但这对于使用未定义__SIZEOF_INT128__.

There might be some 64-bit ISAs where gcc doesn't define __int128, or maybe even some 32-bit ISAs where gcc doesdefine __int128, but I'm not aware of any.

可能有一些 64 位 ISA,其中 gcc 没有定义__int128,甚至可能有一些 32 位 ISA,其中 gcc确实定义了__int128,但我不知道任何。



As comments on another answer here point out, the GCC internals are integer TI mode. (Tetra-integer = 4x width of int, vs. DImode = double width vs. SImode = plain int.) As the GCC manual points out, __int128is supported on targets that support a 128-bit integer mode (TImode).

正如对此处另一个答案的评论指出的那样,GCC 内部是整数 TI 模式。(Tetra-integer = 4x width of int, vs. DImode = double width vs. SImode = plain int。)正如GCC 手册指出的那样__int128支持 128 位整数模式 (TImode) 的目标支持。

// __uint128_t is pre-defined equivalently to this
typedef unsigned uint128 __attribute__ ((mode (TI)));


Random fact: ICC19 and g++/clang++ -E -dMdefine:

随机事实:ICC19 和 g++/clang++-E -dM定义:

#define __GLIBCXX_TYPE_INT_N_0 __int128
#define __GLIBCXX_BITSIZE_INT_N_0 128

@MarcGlisse commented that's the way you tell libstdc++ to handle extra integer types (overload abs, specialize type traits, etc)

@MarcGlisse 评论说,这就是你告诉 libstdc++ 处理额外整数类型(重载 abs、专门化类型特征等)的方式

icpcdefines that even with -xc(to compile as C, not C++), while g++ -xc and clang++ -xc don't. But compiling with actual icc(e.g. select C instead of C++ in the Godbolt dropdown) doesn't define this macro.

icpc定义即使使用-xc(编译为 C,而不是 C++),而 g++ -xc 和 clang++ -xc 则不然。但是用实际编译icc(例如在 Godbolt 下拉列表中选择 C ​​而不是 C++)并没有定义这个宏。



The test function was:

测试函数是:

#include <stdint.h>   // for uint64_t

#define uint128_t __uint128_t
//#define uint128_t unsigned __int128

uint128_t mul64(uint64_t a, uint64_t b) {
    return (uint128_t)a * b;
}

compilers that support it all compile it efficiently, to

支持它的编译器都有效地编译它,以

    mov       rax, rdi
    mul       rsi
    ret                  # return in RDX:RAX which mul uses implicitly

回答by slezica

Ah, big integers are not C's forte.

啊,大整数不是 C 的强项。

GCC does have an unsigned __int128/__int128type, starting from version 4.something (not sure here). I do seem to recall, however, that there was a __int128_tdef before that.

GCC 确实有一个unsigned __int128/__int128类型,从版本 4.something 开始(这里不确定)。然而,我似乎记得__int128_t在那之前有一个定义。

These are only available on 64-bit targets.

这些仅在 64 位目标上可用。

(Editor's note: this answer used to claim that gcc defined uint128_tand int128_t. None of the versions I tested on the Godbolt compiler explorer define those types without leading __, from gcc4.1 to 8.2 , or clang or ICC.)

(编者注:这个答案过去声称 gcc 定义了uint128_tint128_t。我在 Godbolt 编译器资源管理器上测试的所有版本都没有定义这些类型__,从 gcc4.1 到 8.2 ,或 clang 或 ICC。)

回答by Reed Copsey

You could use a library which handles arbitrary or large precision values, such as the GNU MP Bignum Library.

您可以使用处理任意或大精度值的库,例如GNU MP Bignum Library