<cstdint> vs <stdint.h>

94

Was ist der Unterschied zwischen stdint.hund cstdint?

Beide sind in MSVC (Visual Studio 2010) und gcc-4.5.1 verfügbar. Außerdem definieren beide die intX_t/ uintX_t-Typen (wobei Xdie Größe des Typs in Bytes ist).

  • Wenn die Gründe in beiden Headern gleich sind (tragbare Typen), welche Entscheidungen muss ich treffen, um mich für den einen oder anderen zu entscheiden?

Das stdint.hdefiniert jeden Typ ohne Namespace, der cstdintTyp liegt im stdNamespace.

  • Gibt es einen Grund, die definierten Typen in den stdNamespace aufzunehmen oder nicht aufzunehmen ? Was ist zwischen den beiden Headern unterschiedlich?

cstdinthat keine Dateierweiterung und verwendet das cPräfix, stdint.hverwendet die .hErweiterung.

  • Was sind die Namenskonventionen für diese Header? Das cPräfix gibt an, dass dies eine C-Bibliothek ist. Gibt es einen Grund für die fehlende Dateierweiterung in cstdint?
PaperBirdMaster
quelle
OS X 10.8 fehlt <cstdint>. Hier ist der Fehler, den ich erhalte : ./misc.h:7:10: fatal error: 'cstdint' file not found.
JWW

Antworten:

122

Die ursprüngliche Absicht in C ++ 98 war, dass Sie <cstdint>in C ++ verwenden sollten, um eine Verschmutzung des globalen Namespace zu vermeiden (nicht <cstdint>speziell, das wird nur in C ++ 11 hinzugefügt, sondern die <c*>Header im Allgemeinen).

Die Implementierungen bestanden jedoch weiterhin darin, die Symbole in den globalen Namespace einzufügen, und C ++ 11 bestätigte diese Vorgehensweise [*]. Sie haben also grundsätzlich drei Möglichkeiten:

  • Verwenden <cstdint>Sie jeden von Ihnen verwendeten Integer-Typ und qualifizieren Sie ihn entweder vollständig oder bringen Sie ihn mit using std::int32_t;etc in den Geltungsbereich (ärgerlich, weil ausführlich, aber es ist der richtige Weg, dies wie bei jedem anderen Symbol in der C ++ - Standardbibliothek zu tun).
  • Verwendung <stdint.h>(etwas schlecht, weil veraltet)
  • Verwenden Sie <cstdint>und nehmen Sie an, dass Ihre Implementierung die Symbole in den globalen Namespace einfügt (sehr schlecht, weil nicht garantiert).

In der Praxis vermute ich, dass eine ärgerlich große Menge an Code die letzte Option verwendet, einfach weil es bei einer Implementierung, bei <cstdint>der die Symbole in den globalen Namespace eingefügt werden, einfach ist, dies versehentlich zu tun . Sie sollten versuchen, die erste zu verwenden. Die zweite hat eine Tugend, dass es garantiert ist , Dinge in den globalen Namespace zu stellen, anstatt es vielleicht nur zu tun. Ich denke nicht, dass dies besonders nützlich ist, aber es könnte einige Eingaben ersparen, wenn dies Ihre Priorität ist.

Es gibt eine vierte Option, #include <cstdint>gefolgt von using namespace std;der manchmal nützlich ist, aber es gibt Stellen, an denen Sie die nicht setzen sollten using namespace std;. Unterschiedliche Personen haben unterschiedliche Vorstellungen, wo sich diese Orte befinden, aber "auf oberster Ebene in einer Header-Datei" ist schlechter als "auf oberster Ebene in einer CPP-Datei", was schlechter ist als "in einem begrenzten Bereich". Manche Leute schreiben using namespace std;überhaupt nicht.

[*] Das bedeutet, dass C ++ - Standardheader Inhalte in den globalen Namespace einfügen dürfen, dies jedoch nicht. Sie müssen also vermeiden, mit diesen Symbolen zu kollidieren, können sie jedoch nicht verwenden, da sie möglicherweise nicht vorhanden sind. Grundsätzlich ist der globale Namespace in C ++ ein Minenfeld. Versuchen Sie es zu vermeiden. Man könnte argumentieren, dass das Komitee eine Praxis durch Implementierungen ratifiziert hat, die fast so schädlich ist wie das Festhalten using namespace std;auf oberster Ebene in einer Header-Datei - der Unterschied besteht darin, dass die Implementierungen dies nur für Symbole in der C-Standardbibliothek tun, während using namespace std;dies für C ++ der Fall ist -nur Symbole auch. Es gibt einen Abschnitt im C-Standard, in dem Namen aufgeführt sind, die für zukünftige Ergänzungen des Standards reserviert sind. Es ist keine völlig dumme Idee, diese Namen auch im globalen C ++ - Namespace als reserviert zu behandeln, aber es ist nicht unbedingt erforderlich.

Steve Jessop
quelle
Die einzige unbeantwortete Frage, die noch offen ist, betrifft die Namenskonventionen der Header-Dateien. Kennen Sie dieses Thema?
PaperBirdMaster
24
@PaperBirdMaster: C ++ Standard - Bibliothek - Header nicht Dateierweiterungen haben: <iostream>, <vector>, <cstdlib>, abgesehen von denen , die für C - Kompatibilität mit eingeschlossen: <stdint.h>, <stdlib.h>. Und ja, die Initiale czeigt an, dass <cstdlib>C ++ dem C-Standard-Header entspricht <stdlib.h>, anstatt wie in C ++ völlig neu zu sein <vector>. Es gibt einen C ++ - Header <complex>, daher müssen wir nur hoffen, dass keine zukünftige Version von C einen Standardheader einführt <omplex.h>.
Steve Jessop
@SteveJessop Erm, C99?
SS Anne
1
@ JL2210 beachte, dass er sagte <omplex.h>, nicht <complex.h>. Wenn C hinzugefügt würde <omplex.h>, wäre das C ++ - Äquivalent <complex>.
John Leuenhagen
16

Einschließlich cstdintImportiert die Symbolnamen in den Standard-Namespace und möglicherweise in den globalen Namespace.
Einschließlich stdint.hImportiert die Symbolnamen in den globalen Namespace und möglicherweise in den Standard-Namespace.

Funktionen der C-Standardbibliothek sind auch in der C ++ - Standardbibliothek enthalten und werden als allgemeine Namenskonvention durch ein c an die entsprechenden Namen in der C-Standardbibliothek angehängt.

In C ++ sollten Sie Folgendes verwenden:

#include <cstdint>

und qualifizieren Sie die Symbolnamen, mit denen Sie std::
in C arbeiten, vollständig. Sie sollten Folgendes verwenden:

#include <stdint.h>

Anhang D (normativ) In den Kompatibilitätsmerkmalen heißt es:

D.6 C Standardbibliotheksheader

1 Aus Gründen der Kompatibilität mit der C-Standardbibliothek und dem C-Unicode-TR enthält die C ++ - Standardbibliothek die 25 C-Header (siehe Tabelle 151).

Die einschließen:

<assert.h> <float.h> <math.h> <stddef.h> <tgmath.h> <complex.h> <inttypes.h> <setjmp.h> <stdio.h> <time.h> <ctype.h> <iso646.h> <signal.h> <stdint.h> <uchar.h> <errno.h> <limits.h> <stdarg.h> <stdlib.h> <wchar.h> <fenv.h> <locale.h> <stdbool.h> <string.h> <wctype.h>

Und weiter,

2 Jeder C-Header, von dem jeder einen Namen des Formulars hat name.h, verhält sich so, als ob jeder Name, der vom entsprechenden im Standardbibliotheks-Namespace cname headerplatziert wird, innerhalb des globalen Namespace-Bereichs platziert wird. Es ist nicht spezifiziert, ob diese Namen zuerst im Namespace-Bereich (3.3.6) des Namespace-Standards deklariert oder definiert werden und dann durch explizite using-Deklarationen (7.3.3) in den globalen Namespace-Bereich eingefügt werden.

3 [Beispiel: Der Header <cstdlib>stellt seine Deklarationen und Definitionen sicher im Namespace std bereit. Diese Namen können auch im globalen Namespace angegeben werden. Der Header <stdlib.h>enthält im globalen Namespace mit Sicherheit dieselben Deklarationen und Definitionen wie im C-Standard. Diese Namen können auch im Namespace std angegeben werden. - Beispiel beenden]

Alok Speichern
quelle
-1
  1. cstdintist C ++ 11 Header, stdint.hist C99 Header (C und C ++ sind verschiedene Sprachen!)

  2. MSVC 2008 enthält weder stdint.hnoch cstdint.

  3. Implementierungen von cstdintsind meist einfach #include <stdint.h>mit einigen Namespace- / Sprachkorrekturen.

Hass-Motor
quelle
2
3. ist falsch. cstdintmuss die Implementierungen in den Namespace heben std.
Konrad Rudolph
1
1. ist auch falsch, stdint.h ist als Teil der C ++ - Bibliothek im normativen Anhang D des C ++ - Standards definiert.
Chill
@chill, könnten Sie bitte einen Link zu Anhang D bereitstellen? Hier hat en.cppreference.com/w/cpp/types/integer angegeben, dass es sich um einen C ++ 11-Header handelt.
Hass-Motor
1
@ Hass-Engine, ich schlage vor, Sie schlagen es in Ihrer Kopie des C ++ - Standards nach. Diese Referenzseite wird nicht erwähnt stdint.h. Es gibt kein Argument, cstdintdas ein C ++ - Header ist.
Chill
2
Kein Teil von 1. ist falsch, es sieht nur so aus, als ob Sie sagen, dass stdint.hes nicht Teil von C ++ 11 ist. Tatsächlich wird es von C ++ 11 benötigt. Man könnte sagen, " intist in C ++ 11; longist in C99; C und C ++ sind verschiedene Sprachen!", Und auch kein Teil davon wäre falsch. Mein Beispiel ist jedoch noch irreführender, da C ++ 11 teilweise auf C99 verweist, um den Inhalt von beiden zu definieren, stdint.hund cstdintnicht auf C, um zu definieren int.
Steve Jessop