Ответ 1
128-разрядный целочисленный тип доступен только для 64-разрядных целей, поэтому вам необходимо проверить доступность, даже если вы уже обнаружили последнюю версию GCC. Теоретически gcc может поддерживать целые числа TImode на машинах, где для его хранения потребуется 4 32-битных регистра, но я не думаю, что бывают случаи, когда это происходит.
GCC 4.6 и более поздние __int128
имеют __int128
/unsigned __int128
определенный как встроенный тип. использование
#ifdef __SIZEOF_INT128__
чтобы обнаружить его.
GCC 4.1 и более поздние __int128_t
определяют __int128_t
и __uint128_t
в <stdint.h>
. В последних компиляторах это, по-видимому, определяется в терминах __int128
. (Вам все еще нужно #include <stdint.h>
если вы хотите использовать имя __int128_t
вместо __int128
.)
Я проверил #define uint128_t __uint128_t //#define uint128_t unsigned __int128 uint128_t mul64(uint64_t a, uint64_t+b) {%0a+ return (uint128_t)a+*+b; } #ifdef __SIZEOF_INT128__ int detected_ok(){return 1;} #endif '),l:'5',n:'0',o:'C++ source #1',t:'0')),k:33.32694763729248,l:'4',m:100,n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:g412,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'1',trim:'1'),fontScale:1.2899450879999999,lang:c++,libs:!((name:boost,ver:'167')),options:'-xc -O3',source:1),l:'5',n:'0',o:'x86-64 gcc 4.1.2+(Editor #1,+Compiler+#1)+C++',t:'0')),header:(),k:33.3397190293742,l:'4',m:56.14564870956661,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:icc1301,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'1',trim:'1'),fontScale:1.2899450879999999,lang:c++,libs:!((name:boost,ver:'167')),options:'-xc -O3 -xHOST',source:1),l:'5',n:'0',o:'x86-64 icc 13.0.1+(Editor #1,+Compiler+#2)+C++',t:'0')),header:(),l:'4',m:43.8543512904334,n:'0',o:'',s:0,t:'0')),k:33.3397190293742,l:'3',n:'0',o:'',t:'0'),(g:!((h:compiler,i:(compiler:clang30,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'1',trim:'1'),fontScale:1.2899450879999999,lang:c++,libs:!((name:boost,ver:'167')),options:'-xc -O3',source:1),l:'5',n:'0',o:'x86-64+Clang 3.0.0+(Editor #1,+Compiler+#3)+C++',t:'0')),k:33.33333333333333,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4 rel="nofollow noreferrer">на проводнике компилятора 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
, только стиль unsigned __int128
). Как узнать, определен ли __uint128_t
Некоторые люди до сих пор используют древние версии компиляторов, такие как gcc4.4 в RHEL (RedHat Enterprise Linux), или подобные старые системы. Если вам нужны такие устаревшие версии gcc, вы, вероятно, захотите придерживаться __uint128_t
. И, возможно, определить 64-битность с точки зрения sizeof(int_fast32_t)
который по некоторым причинам равен 8 на некоторых 64-битных ISA. Но не на ILP32 ISA, таких как x32 или ILP32 AArch64, поэтому, возможно, просто проверьте sizeof(void*)
если __SIZEOF_INT128__
не определен.
Могут быть некоторые 64-битные ISA, где gcc не определяет __int128
, или, может быть, даже некоторые 32-битные ISA, где gcc действительно определяет __int128
, но я не знаю ни одного.
Как отмечают комментарии к другому ответу, внутренняя часть GCC является целочисленным режимом TI. (Tetra-integer = 4x width of int
, против DImode = double width против SImode = plain 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