Nach meinem Verständnis sollte intes sich ursprünglich um einen "nativen" Integer-Typ mit zusätzlicher Garantie handeln, dass er mindestens 16 Bit groß sein sollte - etwas, das damals als "vernünftige" Größe galt.
Als 32-Bit-Plattformen häufiger wurden, können wir sagen, dass sich die "angemessene" Größe auf 32 Bit geändert hat:
- Modernes Windows verwendet 32-Bit
intauf allen Plattformen.
- POSIX garantiert
intmindestens 32 Bit.
- C #, Java hat einen Typ,
intder garantiert genau 32 Bit beträgt.
Aber als die 64-Bit-Plattform zur Norm wurde, wurde niemand intzu einer 64-Bit-Ganzzahl erweitert, weil:
- Portabilität: Viel Code hängt von
intder Größe von 32 Bit ab.
- Speicherverbrauch: Eine Verdoppelung der Speichernutzung ist
intin den meisten Fällen möglicherweise nicht zumutbar, da in den meisten Fällen die verwendeten Zahlen viel kleiner als 2 Milliarden sind.
Nun, warum wollen Sie uint32_tzu uint_fast32_t? Aus dem gleichen Grund verwenden Sprachen, C # und Java immer Ganzzahlen mit fester Größe: Der Programmierer schreibt keinen Code und denkt über mögliche Größen unterschiedlicher Typen nach. Er schreibt für eine Plattform und testet Code auf dieser Plattform. Der größte Teil des Codes hängt implizit von bestimmten Größen der Datentypen ab. Und deshalb uint32_tist es in den meisten Fällen eine bessere Wahl - es lässt keine Unklarheiten hinsichtlich seines Verhaltens zu.
Ist es uint_fast32_twirklich der schnellste Typ auf einer Plattform mit einer Größe von 32 Bit oder mehr? Nicht wirklich. Betrachten Sie diesen Code-Compiler von GCC für x86_64 unter Windows:
extern uint64_t get(void);
uint64_t sum(uint64_t value)
{
return value + get();
}
Die generierte Baugruppe sieht folgendermaßen aus:
push
sub $0x20,
mov
callq d <sum+0xd>
add
add $0x20,
pop
retq
Wenn Sie nun get()den Rückgabewert auf uint_fast32_t(unter Windows x86_64 4 Byte) ändern , erhalten Sie Folgendes:
push %rbx
sub $0x20,%rsp
mov %rcx,%rbx
callq d <sum+0xd>
mov %eax,%eax ; <-- additional instruction
add %rbx,%rax
add $0x20,%rsp
pop %rbx
retq
Beachten Sie, dass der generierte Code fast identisch ist, mit Ausnahme zusätzlicher mov %eax,%eaxAnweisungen nach dem Funktionsaufruf, mit denen der 32-Bit-Wert in einen 64-Bit-Wert erweitert werden soll.
Es gibt kein solches Problem, wenn Sie nur 32-Bit-Werte verwenden, aber Sie werden wahrscheinlich solche mit size_tVariablen verwenden (Array-Größen wahrscheinlich?) Und diese sind 64-Bit auf x86_64. Unter Linux sind uint_fast32_tes 8 Bytes, daher ist die Situation anders.
Viele Programmierer verwenden, intwenn sie einen kleinen Wert zurückgeben müssen (sagen wir im Bereich [-32,32]). Dies würde perfekt funktionieren, wenn intes sich um eine native Ganzzahlgröße für Plattformen handelt. Da es sich jedoch nicht um eine 64-Bit-Plattform handelt, ist ein anderer Typ, der dem nativen Plattformtyp entspricht, die bessere Wahl (es sei denn, er wird häufig mit anderen Ganzzahlen kleinerer Größe verwendet).
Grundsätzlich ist, unabhängig davon, was der Standard sagt, uint_fast32_tbei einigen Implementierungen ohnehin ein Fehler aufgetreten. Wenn Sie sich für zusätzliche Anweisungen interessieren, die an einigen Stellen generiert werden, sollten Sie Ihren eigenen "nativen" Ganzzahltyp definieren. Oder Sie können es size_tfür diesen Zweck verwenden, da es normalerweise der nativeGröße entspricht (ich schließe keine alten und undurchsichtigen Plattformen wie 8086 ein, sondern nur Plattformen, auf denen Windows, Linux usw. ausgeführt werden können).
Ein weiteres Zeichen, das anzeigt, dass intes sich um einen nativen Ganzzahltyp handeln sollte, ist die "Ganzzahl-Heraufstufungsregel". Die meisten CPUs können nur Operationen auf nativen Systemen ausführen, sodass 32-Bit-CPUs normalerweise nur 32-Bit-Additionen, Subtraktionen usw. ausführen können (Intel-CPUs sind hier eine Ausnahme). Ganzzahlige Typen anderer Größen werden nur durch Lade- und Speicheranweisungen unterstützt. Beispielsweise sollte der 8-Bit-Wert mit der entsprechenden Anweisung "8-Bit-Vorzeichen laden" oder "8-Bit-Vorzeichen laden" geladen werden und wird nach dem Laden auf 32 Bit erweitert. Ohne die Ganzzahl-Heraufstufungsregel müssten C-Compiler etwas mehr Code für Ausdrücke hinzufügen, die Typen verwenden, die kleiner als der native Typ sind. Leider gilt dies bei 64-Bit-Architekturen nicht mehr, da Compiler in einigen Fällen zusätzliche Anweisungen ausgeben müssen (wie oben gezeigt).