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

Benutzeravatar von Drew McGowen
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.

Benutzeravatar von Manu343726
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.

1412390cookie-checkWie frage ich nach “mindestens” einer Größe eines int in C

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy