Beginnend mit der Ausgabe von 1999 definiert der ISO-C-Standard einen Standard-Header <stdint.h>
die unter anderem die typedefs definiert intmax_t
und uintmax_t
. Diese bezeichnen jeweils “einen (vorzeichenbehafteten|vorzeichenlosen) Integer-Typ, der in der Lage ist, jeden Wert eines beliebigen (vorzeichenbehafteten|unsigned) Integer-Typs darzustellen”.
Zum Beispiel, wenn, wie es typisch ist, die breitesten vorzeichenbehafteten und vorzeichenlosen Integer-Typen sind long long int
und unsigned long long int
die beide typischerweise 64 Bit sind intmax_t
und uintmax_t
könnte in definiert werden <stdint.h>
folgendermaßen:
typedef long long int intmax_t;
typedef unsigned long long int uintmax_t;
Es gibt eine begrenzte Menge vordefinierter vorzeichenbehafteter und vorzeichenloser Integer-Typen, die von signed
, unsigned
und schlicht char
bis zu signed
und unsigned
long long int
.
C99 und C11 erlauben auch das Definieren von Implementierungen erweiterte Integer-Typendie sich von allen Standardtypen unterscheiden und deren Namen implementierungsdefinierte Schlüsselwörter sind.
Sowohl gcc als auch clang unterstützen auf einigen, aber nicht allen Zielen Typen __int128
und unsigned __int128
. Diese verhalten sich wie 128-Bit-Ganzzahltypen, sind es aber nicht behandelt wie erweiterte Integer-Typen, und die Dokumentation für beide Compiler gibt an, dass sie keine erweiterten ganzzahligen Typen unterstützen. Denn diese sind es nicht Integer-Typen wie der Standard den Begriff definiert, die typedefs intmax_t
und uintmax_t
sind für 64-Bit-Typen, nicht für 128-Bit-Typen.
Nichts davon verstößt gegen den C-Standard (Implementierungen müssen keine erweiterten Integer-Typen haben, und sie dürfen beliebige Erweiterungen haben, solange sie keine streng konformen Programme verletzen). Aber es scheint mir, dass es durchaus Sinn machen würde __int128
und unsigned __int128
als erweiterte Integer-Typen behandelt werden, und für intmax_t
und uintmax_t
128-Bit-Typen sein.
Die Begründung für nicht Dabei wird die Größe geändert intmax_t
und uintmax_t
wäre “eine ABI-inkompatible Änderung”.
Das Clang C++-Statusseite heißt es in Fußnote (5):
Für eine Implementierung wie Clang, die keine erweiterten Integer-Typen bereitstellt, sind keine Compileränderungen erforderlich.
__int128
wird nicht als erweiterter ganzzahliger Typ behandelt, da sich ändernintmax_t
wäre eine ABI-inkompatible Änderung.
(Ja, hier geht es hauptsächlich um C++, aber die Regeln sind dieselben wie für C.)
In einem gcc-Fehlerberichtwird behauptet:
sizeof(intmax_t)
wird von verschiedenen LP64-ABIs festgelegt und kann nicht geändert werden
In beiden Fällen wird für diese Behauptung keine Referenz angegeben.
Ein x86_64 ABI-Dokument mit dem Titel „System V Application Binary Interface, AMD64 Architecture Processor Supplement, Draft Version 0.99.6“ nicht erwähnt intmax_t
oder uintmax_t
oder sogar die <stdint.h>
Header. Es spezifiziert Größen und Ausrichtungen für die vordefinierten Integer-Typen (in Abbildung 3.1).
Abschließend meine Frage: Ist die Behauptung, dass die Größen von intmax_t
und uintmax_t
eingeschränkt durch ABI gültig? Wenn ja, welche ABI schreibt eine solche Anforderung vor? (Und übrigens warum?)
(Meiner Meinung nach ist eine solche Anforderung, falls vorhanden, unklug. Sie widerspricht dem Zweck der Erlaubnis des C-Standards, erweiterte Integer-Typen zu definieren, und der beabsichtigten Bedeutung von intmax_t
und uintmax_t
. Es macht es viel schwieriger, 128-Bit-Ganzzahltypen effektiv auf Systemen zu verwenden, die sie unterstützen, während auf anderen Systemen auf schmalere Typen zurückgegriffen wird.)
Aktualisieren: In N2303 mit dem Titel “intmax t, a way out” schlägt Jens Gustedt vor, die Definitionen von zu optimieren [u]intmax_t
um das Hinzufügen erweiterter Integer-Typen zuzulassen, die breiter als sind long long
ohne aktualisieren zu müssen [u]intmax_t
. Zum Beispiel, intmax_t
könnte eine Typdefinition für sein long long
aber die Implementierung könnte immer noch Folgendes bereitstellen: __int128
als ein erweiterter ganzzahliger Typ.
Verweise:
- N1256ein Entwurf des C99-Standards
- N1570ein Entwurf des C11-Standards
- N2303ein Vorschlag von Jens Gustedt
- System V AMD64 ABI
Es gibt ein Argument, dass 64 Bit für die meisten Anwendungen ausreichen. Haben
intmax_t
B. ein Typ mit erweiterter Genauigkeit sein, der Carry/Borrow für Add/Sub und noch mehr Komplexität für Mul/Div erfordert, würde zu mehr aufgeblähtem Code als nötig führen. Grundsätzlich sage ich, dass einige Programmierer davon ausgehen könnenintmax_t
nicht breiter zu sein, als das Ziel effizient unterstützen kann. Das ist kein gutes Argumentseitintmax_t
ist auf den meisten 32-Bit-Rechnern 64-Bit. Es wäre schön, wenn es eine gäbeint128_t
aberintmax_t
kann nicht auf bestehenden Plattformen geändert werden, ohne die Rückwärtskompatibilität zu brechen.– Peter Cordes
5. November 2015 um 20:15 Uhr