代码之家  ›  专栏  ›  技术社区  ›  MetallicPriest

gcc中有128位整数吗?

  •  75
  • MetallicPriest  · 技术社区  · 13 年前

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

    3 回复  |  直到 3 年前
        1
  •  58
  •   Peter Cordes    4 年前

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

    在C++中,考虑一个库,例如 boost::multiprecision::int128_t 与使用自己的typedef(如GCC的 __int128 或Clang’s _BitInt(128) ). 另请参阅 @phuclv's answer 关于另一个问题。

    ISO C23会让你 typedef unsigned _BitInt(128) u128 ,建模依据 clang's feature 最初称为 _ExtInt() 它甚至可以在32位机器上工作;看见 a brief intro to it .当前GCC -std=gnu2x 甚至还不支持这种语法。


    GCC 4.6及更高版本具有 __整数128 / unsigned __int128 定义为内置类型。 使用
    #ifdef __SIZEOF_INT128__ 以检测它。

    GCC 4.1及以后的定义 __int128_t __uint128_t 作为内置类型 (你不需要 #include <stdint.h> 对于这些,也一样。证据 on Godbolt .)

    我测试过 on the Godbolt compiler explorer 编译器的第一个版本支持这三种功能中的每一种(在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或x86)进行编译 -m32 ,即使是这些编译器的最新版本也不支持128位整数类型。 所以你 需要 在使用之前检测支持,如果您的代码可以在没有它的情况下工作的话。

    据我所知,用于检测它的唯一直接CPP宏是 __SIZEOF_INT128__ ,但不幸的是,一些旧的编译器版本在没有定义它的情况下支持它 __uint128_t ,只有gcc4.6样式 无符号__int128 ). How to know if __uint128_t is defined

    有些人仍然使用古老的编译器版本,如RHEL(RedHat Enterprise Linux)上的gcc4.4,或类似的顽固的旧系统。如果你关心这样过时的gcc版本,你可能想坚持 __uint128_t 。并且可能检测到64比特 sizeof(void*) == 8 作为 __尺寸_INT128__ 没有定义。(我认为GNU系统总是 CHAR_BIT==8 ,尽管我可能对某些DSP的看法是错误的)。这将对64位ISA(如x86-64 Linux x32或AArch64 ILP32)上的ILP32 ABI产生假阴性,但对于使用未定义 __尺寸_INT128__ .

    可能有一些64位ISAs中gcc没有定义 __整数128 ,甚至可能是一些32位ISAs,其中gcc 定义 __整数128 ,但我不知道。


    GCC内部为整数TI模式( GCC internals manual ). (四进制整数=32位宽度的4倍 int ,vs.DImode=双倍宽度vs.SImode=普通 整数 .)作为 the GCC manual points out , __整数128 在支持128位整数模式(TImode)的目标上受支持。

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

    手册中有一个OI模式,oct int=32字节,但x86-64的当前GCC抱怨说,如果您尝试使用它,“无法模拟‘OI’”。


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

    #define __GLIBCXX_TYPE_INT_N_0 __int128
    #define __GLIBCXX_BITSIZE_INT_N_0 128
    

    @MarcGlisse评论道 这就是告诉libstdc++处理额外整数类型(重载abs、特殊化类型traits等)的方法

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


    测试功能为:

    #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;
    }
    

    支持这一切的编译器高效地编译它

        mov       rax, rdi
        mul       rsi
        ret                  # return in RDX:RAX which mul uses implicitly
    
        2
  •  34
  •   Peter Cordes    7 年前

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

    GCC确实有 unsigned __int128 / __int128 类型,从版本4开始(此处不确定)。然而,我似乎确实记得 __int128_t 在此之前的def。

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

    (编者按:这个答案曾经声称gcc定义了 uint128_t int128_t 。我在Godbolt编译器资源管理器上测试的版本都没有定义那些没有前导的类型 __ ,从gcc4.1到8.2,或clang或ICC。)

        3
  •  17
  •   Reed Copsey    13 年前

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

    推荐文章