Wie frage ich nach “mindestens” einer Größe eines int in C
Lesezeit: 6 Minuten
Die Situation:
Ich habe eine in C geschriebene Anwendung, die ressourcenintensiv und portabel ist. Ich möchte dem Compiler erlauben, die schnellste Int-Größe für die Architektur auszuwählen, sofern sie mindestens 32 Bit beträgt.
Ist es möglich, eine Größe von “mindestens” 32 Bit auszuwählen, oder optimiert der Compiler solche Dinge automatisch von mir?
Warum das C++-Tag? Ist C++-Kompatibilität erforderlich?
– Niall
21. Juli 2014 um 13:29 Uhr
Ich denke, es ist was long ist für.
– QUentin
21. Juli 2014 um 13:31 Uhr
Du suchst nach stdint.h typedefs, wie int_least32_t
– geröstete_Flocken
21. Juli 2014 um 13:31 Uhr
@Quentin: Nein, ist es nicht.
– Kaiserludi
21. Juli 2014 um 16:17 Uhr
@Quentin: Und wo garantiert der Standard, dass long immer der schnellste Integer-Typ einer Architektur ist?
– Kaiserludi
21. Juli 2014 um 18:13 Uhr
Drew McGowen
Der Standard-Header stdint.h liefert die Typen int_leastN_t und uint_leastN_two N ist 8, 16, 32 und 64 (und möglicherweise andere, aber diese sind nicht erforderlich). Diese sind ab C99 Standard.
Es bietet auch “schnelle” Alternativen, alias int_fastN_t und uint_fastN_tmit den gleichen Werten von N.
In Ihrem Fall können Sie also verwenden int_least32_t oder int_fast32_t.
int_fast32_t ist, was das OP hier braucht. int_least32_t ist nicht der schnellste Integer-Typ mit 32+ Bits, sondern nur der kleinste.
– TonyK
21. Juli 2014 um 13:41 Uhr
Danke, genau das wollte ich wissen.
– derekdreery
21. Juli 2014 um 15:38 Uhr
Außer dass int_fast32_t ist auf wichtigen Archs wie x86_64 falsch definiert, wo es eigentlich a ist viel langsamer Typ (64-Bit statt 32-Bit): z +/-/* beide sind identisch schnell, aber z / es ist viel langsamer, und natürlich sind Lade-/Speichervorgänge langsamer, da Sie doppelt so viele Cache-Zeilen und doppelt so viel Speicherbandbreite verwenden. Also würde ich wirklich zögern, es zu benutzen. Ich bin mir nicht bewusst irgendein arch mit einem 32-Bit-int, wo es nicht der schnellste Typ für die Arbeit mit “mindestens 32-Bit”-Ganzzahlen ist.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
22. Juli 2014 um 4:42 Uhr
@R..: Sollte nicht dasselbe gelten für short? Das heißt, die Aufteilung von Shorts sollte nicht schneller sein (vorausgesetzt, sie sind tatsächlich kleiner und C hat sie nicht automatisch dazu befördert int)?
– Benutzer541686
22. Juli 2014 um 10:52 Uhr
@Mehrdad: Wahrscheinlich, aber oft da ist zusätzliche Kosten für das Laden/Lagern und Durchführen von Operationen an Shorts. Auf einigen alten x86-Systemen verhinderte das Präfix der Operandengröße das Pipelining; vielleicht sind die einzigen Kosten jetzt eine erhöhte Nutzung des Befehls-Cache. Dies ist natürlich ein weiterer Grund, warum die “schnellen” Typen fehlgeleitet sind – welcher Typ schneller ist, kann sehr wohl vom spezifischen CPU-Modell abhängen, nicht nur vom ISA. Und Sie können den Typ praktisch nicht ändern, je nachdem -march oder so, weil das ABI kaputt machen würde.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
22. Juli 2014 um 12:59 Uhr
Wie andere angemerkt haben, definieren die Standard-Include-Dateien int_fast32_t, int_least32_t, uint_fast32_t, uint_least32_t die sich wahrscheinlich so verhalten sollten, wie Sie es möchten, aber solche Typen müssen mit äußerster Sorgfalt verwendet werden. Aufgrund der Heraufstufungsregeln für ganze Zahlen gibt es für C-Code keine Möglichkeit, die Verwendung von Typen zu vermeiden int und unsigned int. Außerdem sind Integer-Literale möglicherweise nicht immer die Typen, die man erwartet. Ein Vergleich zwischen einem int_fast32_T und die Literale 0xABCD1234 oder 12345ukann zum Beispiel entweder mit Vorzeichen oder ohne Vorzeichen ausgeführt werden, je nachdem, ob int ist 16, 32 oder 64 Bit. Ebenso wenn n ist 32 Bit oder größer, die Bedeutung von n &= ~0x8000; auf einem 16-Bit-Rechner anders wäre als auf einem größeren.
Der C-Standard wurde nie speziell entwickelt, um das Schreiben von Code zu erleichtern, der sich um ganzzahlige Größen kümmert, funktioniert aber dennoch kompatibel auf Hardware mit unterschiedlichen Größen. Typen wie int_fast32_t Machen Sie es einfach, Code zu schreiben, der so aussieht, als ob er portabel sein sollte, aber die Selbstgefälligkeit in Bezug auf all die bösen kleinen Fallen, die in der Sprache versteckt sind, fördern kann.
Manu343726
Diese Frage wurde auch als C++ gekennzeichnet, daher ist hier eine Lösung für Liebhaber der Template-Metaprogrammierung wie mich.
Anforderungen
Ein Typlistentyp mit dem Namen list hier.
Ein Haskell-ähnliches filter Metafunktion.
EIN head Metafunktion, um das erste Element einer Typliste zu erhalten.
Der Code
Diese Lösung automatisiert die akzeptierte Lösung (was gerecht ist “gehe zu stdint.h und wählen Sie das Passende für Sie aus”). Diese Aufgabe könnte vom Compiler erledigt werden, oder?
Listen Sie zuerst alle plattformspezifischen schnellsten Integer-Typen auf, die deklariert wurden <cstdint>:
using integer_types = list<std::int_fast8_t,std::int_fast16_t,
std::int_fast32_t,std::int_fast64_t>;
Beachten Sie, dass die Liste nach aufsteigender ganzzahliger Größe sortiert ist.
Definieren Sie nun ein Filterprädikat. In unserem Fall sollte die Größe kleiner sein als die vom Benutzer angegebene Größe (nennen Sie es SIZE):
template<typename T>
using f = std::integral_constant<bool,sizeof(T)*CHAR_BITS <= SIZE>;
Filtern Sie dann die Liste der Integer-Typen und erhalten Sie das erste Element des Ergebnisses:
using best_integer_t = head<filter<f,integer_types>>;
Zusammengefasste Lösung
template<std::size_t SIZE>
struct fastest_integer_impl
{
//Guard for the case the user specified less than one byte size:
static constexpr const std::size_t size = SIZE >= CHAR_BITS ? size : CHAR_BITS;
using integer_types = list<std::int_fast8_t,std::int_fast16_t,
std::int_fast32_t,std::int_fast64_t>;
template<typename T>
using f = std::integral_constant<bool,sizeof(T)*CHAR_BITS <= size>;
using type = head<filter<f,integer_types>>;
};
template<std::size_t SIZE>
using fastest_integer = typename fastest_integer_impl<SIZE>::type;
Gewohnheit fastest_integer<4> gib das gleiche wie std::int_fast32_t? Wie ist das besser als nur direkt zu verwenden std::int_fast32_t?
– Peter SW
21. Juli 2014 um 17:49 Uhr
@PeterSW Entschuldigung, war ein Tippfehler bei der Implementierung. Die Metafunktion sollte mit der Größe in Bits arbeiten. Der Zweck der Metafunktion besteht darin, den ganzzahligen Auswahlprozess zu automatisieren. Etwas wie “Ich arbeite mit 20 Bit, was ist der schnellste Integer-Typ, den Sie mit mindestens dieser Größe haben?”
– Manu343726
21. Juli 2014 um 18:40 Uhr
Danke für etwas C++ 🙂
– derekdreery
22. Juli 2014 um 14:07 Uhr
am schnellsten => mit Pragma Pack an der Architektur ausrichten. Ohne dies würde für den Fall, dass der Speicher nicht ausgerichtet ist, mehr als ein Speicherzugriff erforderlich sein.
min 32 => int specifier verwenden – genug. Dies stellt meines Wissens 32 Bit in Linux über alle Architekturen sicher.
14123900cookie-checkWie frage ich nach “mindestens” einer Größe eines int in Cyes
Warum das C++-Tag? Ist C++-Kompatibilität erforderlich?
– Niall
21. Juli 2014 um 13:29 Uhr
Ich denke, es ist was
long
ist für.– QUentin
21. Juli 2014 um 13:31 Uhr
Du suchst nach
stdint.h
typedefs, wieint_least32_t
– geröstete_Flocken
21. Juli 2014 um 13:31 Uhr
@Quentin: Nein, ist es nicht.
– Kaiserludi
21. Juli 2014 um 16:17 Uhr
@Quentin: Und wo garantiert der Standard, dass long immer der schnellste Integer-Typ einer Architektur ist?
– Kaiserludi
21. Juli 2014 um 18:13 Uhr