В gcc есть 128-битное целое число?

Я хочу 128-битное целое число, потому что я хочу хранить результаты умножения двух 64-битных чисел. Есть ли такая вещь в gcc 4.4 и выше?

2 ответа

128-разрядный целочисленный тип доступен только для 64-разрядных целей, поэтому вам необходимо проверить доступность, даже если вы уже обнаружили последнюю версию GCC. Теоретически gcc может поддерживать целые числа TImode на машинах, где для его хранения потребуется 4 32-битных регистра, но я не думаю, что бывают случаи, когда это происходит.


GCC 4.6 и позже имеет __int128 / unsigned __int128 определяется как встроенный тип.

GCC 4.1 и позже определяют __int128_t а также __uint128_t в <stdint.h>, На последних компиляторах это, вероятно, определяется с точки зрения __int128,

Я проверил на проводнике компилятора Godbolt первые версии компиляторов для поддержки каждой из этих трех вещей (на 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 unsigned __int128). Как узнать, определен ли __uint128_t

Некоторые люди до сих пор используют древние версии компиляторов, такие как gcc4.4 в RHEL (RedHat Enterprise Linux), или подобные старые системы. Если вы заботитесь об устаревших версиях gcc, возможно, вы захотите придерживаться __uint128_t, И, возможно, обнаружить 64-битность с точки зрения sizeof(int_fast32_t) который по некоторым причинам 8 на некоторых 64-битных ISA. Но не на ILP32 ISA, таких как x 32 или ILP32 AArch64, так что, возможно, просто проверьте sizeof(void*) если __SIZEOF_INT128__ не определено

Там могут быть некоторые 64-битные ISA, где gcc не определяет __int128 или, может быть, даже некоторые 32-битные ISA, где gcc определяет __int128, но я не знаю ни о чем.

Как отмечают комментарии к другому ответу, внутренняя часть GCC является целочисленным режимом TI. (Tetra-integer = 4x ширина int, против DImode = двойная ширина против SImode = обычный int.) Как указывает руководство GCC, __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

Ах, большие целые числа не являются сильной стороной Си.

GCC имеет uint128_t/int128_t Тип, начиная с версии 4. что-то (не уверен здесь). Я, кажется, помню, однако, что был __int128_t Def до этого.

Вы можете использовать библиотеку, которая обрабатывает значения произвольной или большой точности, например библиотеку GNU MP Bignum.

Другие вопросы по тегам