我想要一个128位整数,因为我想要存储两个64位数字的乘法结果.gcc 4.4及以上版本中是否有此类内容?

推荐答案

128位整数类型是only ever available on 64-bit targets,所以即使您已经检测到最新的GCC版本,也需要判断可用性.理论上,gcc could在需要4个32位寄存器才能保存的机器上支持TImode整数,但我认为在任何情况下都不支持.


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

GCC 4.1 and later define 101 and 102 as built-in types.(这些也不需要#include <stdint.h>元.证据on Godbolt.)

I tested on the Godbolt compiler explorer for 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.

         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 100, no 128-bit integer type is supported with even the newest version of any of these compilers.,因此您需要在使用之前检测支持,如果您的代码在没有支持的情况下也可以工作的话.

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

有些人仍然使用古老的编译器版本,比如gcc4.4在RHEL(RedHat Enterprise Linux)或类似的老旧系统上.如果你关心像这样过时的gcc版本,你可能想坚持使用__uint128_t.可能会检测sizeof(void*) == 8的64位,作为__SIZEOF_INT128__未定义的回退.(我认为GNU系统总是有CHAR_BIT==8个).这将导致64位ISA(如x86-64 Linux x32或AArch64 ILP32)上的ILP32 ABI出现假阴性,但对于使用不定义__SIZEOF_INT128__的旧编译器的人来说,这已经只是一个退步/额外的好处.

可能有一些64位的ISA,GCC没有定义__int128,或者甚至有一些32位的ISA,GCC定义了__int128,但我不知道有什么.


正如对另一个答案的 comments 所指出的,GCC内部是整数TI模式.(Tetra integer=int的4x宽度,vs.DImode=双倍宽度vs.SImode=普通int.)As the GCC manual points out__int128在支持128位整数模式(TImode)的目标上受支持.

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

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

#define __GLIBCXX_TYPE_INT_N_0 __int128
#define __GLIBCXX_BITSIZE_INT_N_0 128

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

icpc定义了即使是-xc(编译为C,而不是C++),而G++-XC和CLAN++XC不这样.但是编译实际icc(例如, Select C++而不是C++中的GOOBED下拉)不定义这个宏.


测试功能为:

#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

C++相关问答推荐

如果实际的syscall是CLONE(),那么为什么strace接受fork()呢?

编译SDL 2时缺少SDL_ttf

C/SDL程序,渲染不使用我的渲染器

如何将字符串argv[]赋给C中的整型数组?

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

CSAPP微型shell 实验室:卡在sigprocmask

pthread_create的用法

C标准关于外部常量的说明

使用C++中的字符串初始化 struct 时,从‘char*’初始化‘char’使指针变为整数,而不进行强制转换

为什么我无法访问C语言中的文件

Fscanf打印除退出C代码为1的程序外的所有内容

即使我在C++中空闲,也肯定会丢失内存

被调用方函数内部的C-Struct变量,它是指针还是无关紧要

从文件到链表读取日期

计算时出现奇怪的计算错误;N Select K;在C中

GnuCobol 使用 double 类型的参数调用 C 函数

SSE 向量与 Epsilon 的比较

段错误try 访问静态字符串,但仅有时取决于构建环境

无法在 C 中打开文本文件,我想从中读取文本作为数据并将其写入数组

在 C 中有效返回多个值