wake-up-neo.com

Gibt es eine 128-Bit-Ganzzahl in gcc?

Ich möchte eine 128-Bit-Ganzzahl, weil ich Multiplikationsergebnisse von zwei 64-Bit-Zahlen speichern möchte. Gibt es so etwas in gcc 4.4 und höher?

34
MetallicPriest

Ein 128-Bit-Integer-Typ ist immer nur auf 64-Bit-Zielen verfügbar. Sie müssen daher die Verfügbarkeit prüfen, auch wenn Sie bereits einen aktuellen GCC erkannt haben Ausführung. Theoretisch unterstützt gcc could TImode-Ganzzahlen auf Computern, auf denen 4x 32-Bit-Register erforderlich sind, um ein Register zu speichern, aber ich glaube, es gibt keine Fälle, in denen dies der Fall ist.


In GCC 4.6 und höher ist ein __int128/unsigned __int128 Als integrierter Typ definiert. Verwendung
#ifdef __SIZEOF_INT128__, um es zu erkennen.

GCC 4.1 und höher definieren __int128_t Und __uint128_t In <stdint.h>. Bei neueren Compilern wird dies vermutlich in Form von __int128 Definiert. (Sie müssen immer noch #include <stdint.h> Eingeben, wenn Sie den Namen __int128_t Anstelle von __int128 Verwenden möchten.)

Ich habe im Godbolt-Compiler-Explorer getestet, damit die ersten Compilerversionen diese drei Dinge unterstützen (auf x86-64). Godbolt geht nur auf gcc4.1, ICC13 und clang3.0 zurück, daher habe ich <= 4.1 verwendet, um anzuzeigen, dass die eigentliche erste Unterstützung möglicherweise noch früher erfolgt ist.

         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)

Wenn Sie für eine 32-Bit-Architektur wie ARM oder x86 mit -m32 Kompilieren, wird auch mit der neuesten Version eines dieser Compiler kein 128-Bit-Integer-Typ unterstützt. Sie müssen also müssen Unterstützung vor der Verwendung erkennen, wenn es möglich ist, dass Ihr Code ohne sie überhaupt funktioniert.

Das einzige direkte CPP-Makro, das mir bekannt ist, um es zu erkennen, ist __SIZEOF_INT128__, Aber leider unterstützen einige alte Compilerversionen es, ohne es zu definieren. (Und es gibt kein Makro für __uint128_t, Nur den gcc4.6-Stil unsigned __int128). Woher wissen, ob __uint128_t definiert ist

Einige Leute verwenden immer noch alte Compilerversionen wie gcc4.4 auf RHEL (RedHat Enterprise Linux) oder ähnlichen verkrusteten alten Systemen. Wenn Sie sich für veraltete gcc-Versionen wie diese interessieren, möchten Sie sich wahrscheinlich an __uint128_t Halten. Und vielleicht erkennen Sie 64-Bit-Werte in Form von sizeof(int_fast32_t), die auf einigen 64-Bit-ISAs aus irgendeinem Grund 8 betragen. Aber nicht auf ILP32-ISAs wie x32 oder ILP32 AArch64. Prüfen Sie also vielleicht einfach sizeof(void*), wenn __SIZEOF_INT128__ Nicht definiert ist.

Es gibt möglicherweise 64-Bit-ISAs, in denen gcc nicht __int128 Definiert, oder sogar 32-Bit-ISAs, in denen gcc tut__int128 Definiert, aber Mir sind keine bekannt.

Wie Kommentare zu einer anderen Antwort hier zeigen, handelt es sich bei den GCC-Interna um den Ganzzahl-TI-Modus. (Tetra-Integer = 4x Breite von int vs. DImode = doppelte Breite vs. SImode = einfaches int.) Wie weist das GCC-Handbuch darauf hin , __int128 Wird auf Zielen unterstützt, die einen 128-Bit-Ganzzahlmodus (TImode) unterstützen.

typedef unsigned uint128_t __attribute__ ((mode (TI)));

Zufällige Tatsache: ICC19 -E -dM Definiert:

#define __GLIBCXX_TYPE_INT_N_0 __int128
#define __GLIBCXX_BITSIZE_INT_N_0 128

Die Testfunktion war:

#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;
}

compiler, die alles unterstützen, kompilieren es effizient, um

    mov       rax, rdi
    mul       rsi
    ret                          # return in RDX:RAX
13
Peter Cordes

Ah, große ganze Zahlen sind keine Stärke von C.

GCC hat einen Typ unsigned __int128/__int128, Ab Version 4.etwas (hier nicht sicher). Ich scheine mich jedoch zu erinnern, dass es davor einen __int128_t Def gab.

Diese sind nur auf 64-Bit-Zielen verfügbar.

(Anmerkung des Herausgebers: Diese Antwort wurde verwendet, um zu behaupten, dass gcc uint128_t Und int128_t Definiert. Keine der im Godbolt-Compiler-Explorer getesteten Versionen definiert diese Typen ohne vorangestelltes __ Von gcc4.1 bis 8.2 oder clang oder ICC.)

31
slezica

Sie könnten eine Bibliothek verwenden, die beliebige oder sehr genaue Werte verarbeitet, wie z. B. GNU MP Bignum Library .

13
Reed Copsey