В 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.