Мне нужно 128-битное целое число, потому что я хочу сохранить результаты умножения двух 64-битных чисел. Есть ли такое в gcc 4.4 и выше?
Есть ли в gcc 128-битное целое число?
Ответы (3)
128-битный целочисленный тип доступен только для 64-битных целей, поэтому вам необходимо проверить доступность, даже если вы уже обнаружили последнюю версию GCC. Теоретически gcc может поддерживать целые числа TImode на машинах, где для их хранения потребуется 4 32-битных регистра, но я не думаю, что есть какие-либо случаи, когда это возможно.
GCC 4.6 и более поздних версий имеет __int128
/ unsigned __int128
, определенный как встроенный тип. Используйте #ifdef __SIZEOF_INT128__
для его обнаружения.
GCC 4.1 и более поздние версии определяют __int128_t
и __uint128_t
как встроенные типы. (Вам не нужно #include <stdint.h>
для них, либо. Доказательство на Godbolt.)
Если вы компилируете для 32-битной архитектуры, такой как ARM или x86 с -m32
, 128-битный целочисленный тип не поддерживается даже в новейшей версии любого из этих компиляторов. Итак, вам понадобится < / em> для обнаружения поддержки перед использованием, если ваш код вообще может работать без нее.
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)
Единственный известный мне прямой макрос CPP для его обнаружения - это __SIZEOF_INT128__
, но, к сожалению, некоторые старые версии компилятора поддерживают его, не определяя его. (И нет макроса для __uint128_t
, только стиль gcc4.6 unsigned __int128
). Как узнать, определено ли __uint128_t
Некоторые люди до сих пор используют старые версии компилятора, такие как gcc4.4 на RHEL (RedHat Enterprise Linux), или аналогичные старые системы. Если вас беспокоят подобные устаревшие версии gcc, вы, вероятно, захотите придерживаться __uint128_t
. И, возможно, обнаружит 64-битность в терминах sizeof(void*) == 8
как запасной вариант для __SIZEOF_INT128__
не определено. (Я думаю, что в системах GNU всегда есть CHAR_BIT==8
). Это даст ложный отрицательный результат для ABI ILP32 на 64-битных ISA (например, x86-64 Linux x32 или AArch64 ILP32), но это уже просто резерв / бонус для людей, использующих старые компиляторы, которые не определяют __SIZEOF_INT128__
.
Могут быть некоторые 64-битные ISA, где gcc не определяет __int128
, или, может быть, даже некоторые 32-битные ISA, где gcc действительно определяет __int128
, но я не знаю ни одного.
Как указывается в комментариях к другому ответу, внутреннее устройство GCC является целочисленным режимом TI. (Tetra-integer = 4x ширина int
, по сравнению с DImode = двойная ширина по сравнению с SImode = plain int
.) Как указано в руководстве GCC, __int128
поддерживается на целевых объектах, которые поддерживают 128-битный целочисленный режим (TImode).
Случайный факт: ICC19 и g ++ / clang ++ -E -dM
определяют:
// __uint128_t is pre-defined equivalently to this
typedef unsigned uint128 __attribute__ ((mode (TI)));
@MarcGlisse прокомментировал , как вы указываете libstdc ++ обрабатывать дополнительные целочисленные типы (перегрузка abs, особые свойства типов и т. Д.)
#define __GLIBCXX_TYPE_INT_N_0 __int128
#define __GLIBCXX_BITSIZE_INT_N_0 128
icpc
определяет это даже с -xc
(для компиляции как C, а не C ++), в то время как g ++ -xc и clang ++ -xc этого не делают. Но компиляция с фактическим icc
(например, выберите C вместо C ++ в раскрывающемся списке Godbolt) не определяет этот макрос.
Тестовая функция была:
компиляторы, которые поддерживают все это, компилируют его эффективно, чтобы
#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
unsigned __int128
.
- person Brett Hale; 01.07.2019
divisor > high_half_dividend
s на x86_64 - 32 бита, glibc - 64 (в этом отношении тоже не рекомендуется включать в API).
- person Peter Cordes; 01.07.2019
-xc
- это 64 бита во всех реализациях, которые я использовал, включая GCC для x86-64. И я считаю, что 128-битное int GCC доступно только на 64-битных платформах.
- person Peter Cordes; 26.01.2020
GCC действительно имеет тип _1 _ / _ 2_, начиная с версии 4.something (здесь не уверен). Однако я, кажется, припоминаю, что до этого было __int128_t
def.
Они доступны только для 64-битных целей.
(Примечание редактора: в этом ответе утверждалось, что gcc определяет uint128_t
и int128_t
. Ни одна из версий, которые я тестировал в обозревателе компилятора Godbolt, не определяет эти типы без начала __
, от gcc4.1 до 8.2, или clang или ICC.)
Вы можете использовать библиотеку, которая обрабатывает произвольные или большие значения точности, такую как GNU MP Bignum Library.
[]int128_t
. Работает давно (на архитектурах с нативной 64-битной).
- person Keith Thompson; 18.04.2013
typedef int really_long __attribute__ ((mode (TI)));
и выше поддерживают _2_ "из коробки", а также поддерживают следующий typedef: _3_.
- person Pascal Cuoq; 19.04.2013
Взгляните: stackoverflow.com/questions/3329541/