<cstdint> contre <stdint.h>

95

Quelle est la différence entre stdint.het cstdint?

Les deux sont disponibles dans MSVC (Visual Studio 2010) et gcc-4.5.1. Les deux définissent également les types intX_t/ uintX_t(où Xest la taille en octets du type).

  • Si la justification dans les deux en-têtes est la même (types portables), quelles décisions dois-je prendre pour décider de l'un ou de l'autre?

Le stdint.hdéfinit chaque type sans aucun espace de noms, les cstdinttypes se trouvent dans l' stdespace de noms.

  • Y a-t-il une raison d'inclure ou de ne pas inclure les types définis dans l' stdespace de noms? Quelle est la différence entre les deux en-têtes?

cstdintn'a pas d'extension de fichier et utilise le cpréfixe, stdint.hutilise l' .hextension.

  • Quelles sont les conventions de dénomination de ces en-têtes? le cpréfixe indique qu'il s'agit d'une bibliothèque C? il y a une raison pour le manque d'extension de fichier dans cstdint?
PaperBirdMaster
la source
OS X 10.8 manque <cstdint>. Voici l'erreur que je reçois: ./misc.h:7:10: fatal error: 'cstdint' file not found.
jww

Réponses:

122

L'intention originale dans C ++ 98 était que vous devriez utiliser <cstdint>en C ++, pour éviter de polluer l'espace de noms global (enfin, pas <cstdint>en particulier, cela n'est ajouté qu'en C ++ 11, mais les en- <c*>têtes en général).

Cependant, les implémentations ont persisté à placer les symboles dans l'espace de noms global de toute façon, et C ++ 11 a ratifié cette pratique [*]. Donc, vous avez essentiellement trois options:

  • Utilisez <cstdint>et qualifiez complètement chaque type d'entier que vous utilisez ou mettez-le dans la portée avec using std::int32_t;etc (ennuyeux car verbeux, mais c'est la bonne façon de le faire comme pour tout autre symbole de la bibliothèque standard C ++)
  • Utilisation <stdint.h>(légèrement mauvaise car obsolète)
  • Utilisez <cstdint>et supposez que votre implémentation placera les symboles dans l'espace de noms global (très mauvais car non garanti).

En pratique, je soupçonne qu'une grande quantité de code ennuyeuse utilise la dernière option, simplement parce que c'est facile à faire par accident sur une implémentation où <cstdint>met les symboles dans l'espace de noms global. Vous devriez essayer d'utiliser le premier. Le second a une vertu, c'est qu'il est garanti de mettre des choses dans l'espace de noms global au lieu de le faire peut-être seulement. Je ne pense pas que ce soit particulièrement utile, mais cela pourrait vous faire gagner du temps si c'est votre priorité.

Il y a une quatrième option, #include <cstdint>suivie de using namespace std;laquelle est parfois utile, mais il y a des endroits où vous ne devriez pas mettre le fichier using namespace std;. Différentes personnes auront des idées différentes où se trouvent ces endroits, mais «au niveau supérieur dans un fichier d'en-tête» est pire que «au niveau supérieur dans un fichier cpp», ce qui est pire que «dans une portée limitée». Certaines personnes n'écrivent jamais using namespace std;du tout.

[*] Cela signifie que les en-têtes standards C ++ sont autorisés à placer des éléments dans l'espace de noms global mais pas obligés de le faire. Vous devez donc éviter d'entrer en collision avec ces symboles, mais vous ne pouvez pas les utiliser car ils pourraient ne pas être là. Fondamentalement, l'espace de noms global en C ++ est un champ de mines, essayez de l'éviter. On pourrait soutenir que le comité a ratifié une pratique par des implémentations qui est presque aussi nuisible que de rester using namespace std;au niveau supérieur dans un fichier d'en-tête - la différence étant que les implémentations ne le font que pour les symboles de la bibliothèque standard C, alors using namespace std;que pour C ++ -seulement symboles aussi. Il y a une section dans la norme C qui répertorie les noms réservés pour de futurs ajouts à la norme. Ce n'est pas une idée complètement stupide de traiter ces noms comme réservés dans l'espace de noms global C ++, mais ce n'est pas essentiel.

Steve Jessop
la source
La seule question sans réponse qui reste concerne les conventions de dénomination des fichiers d'en-tête, connaissez-vous ce sujet?
PaperBirdMaster
24
@PaperBirdMaster: les en- têtes de la bibliothèque standard C + ne sont pas des extensions de fichier: <iostream>, <vector>, <cstdlib>, à l' exception de ceux qui sont inclus pour assurer la compatibilité C: <stdint.h>, <stdlib.h>. Et oui, l'initiale cindique que <cstdlib>c'est l'équivalent en C ++ de l'en-tête standard C <stdlib.h>, plutôt que d'être totalement nouveau en C ++ comme l' <vector>est. Il y a un en-tête C ++ <complex>, donc nous devrons juste espérer qu'aucune future version de C n'introduira un en-tête standard <omplex.h>.
Steve Jessop
@SteveJessop Euh, C99?
SS Anne
1
@ JL2210 remarque qu'il a dit <omplex.h>, non <complex.h>. Si C ajouté <omplex.h>, l'équivalent C ++ serait <complex>.
John Leuenhagen
16

Y compris cstdintimporte les noms de symboles dans l'espace de noms std et éventuellement dans l'espace de noms Global.
Y compris stdint.himporte les noms de symboles dans l'espace de noms Global et éventuellement dans l'espace de noms std.

Les fonctionnalités de la bibliothèque standard C sont également fournies dans la bibliothèque standard C ++ et en tant que convention de dénomination générale, elles sont précédées d'un c aux noms correspondants dans la bibliothèque standard C.

En C ++, vous devriez utiliser:

#include <cstdint>

et qualifiez complètement les noms de symboles que vous utilisez avec std::
en C, vous devez utiliser:

#include <stdint.h>

L'Annexe D (normative) Caractéristiques de compatibilité [depr] stipule:

D.6 En-têtes de bibliothèque standard C

1 Pour la compatibilité avec la bibliothèque standard C et le C Unicode TR, la bibliothèque standard C ++ fournit les 25 en-têtes C, comme indiqué dans le tableau 151.

Qui inclut:

<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>

Et plus loin,

2 Chaque en-tête C, dont chacun a un nom de formulaire name.h, se comporte comme si chaque nom placé dans l'espace de noms de bibliothèque standard par le correspondant cname headerétait placé dans la portée de l'espace de noms global. Il n'est pas précisé si ces noms sont d'abord déclarés ou définis dans la portée d'espace de noms (3.3.6) de l'espace de noms std et sont ensuite injectés dans la portée d'espace de noms global par des déclarations d'utilisation explicites (7.3.3).

3 [Exemple: l'en-tête <cstdlib>fournit assurément ses déclarations et définitions dans l'espace de noms std. Il peut également fournir ces noms dans l'espace de noms global. L'en-tête <stdlib.h>fournit assurément les mêmes déclarations et définitions dans l'espace de noms global, tout comme dans le C Standard. Il peut également fournir ces noms dans l'espace de noms std. —End exemple]

Alok Save
la source
-1
  1. cstdintest l'en-tête C ++ 11, stdint.hest l'en-tête C99 (C et C ++ sont des langages différents!)

  2. MSVC 2008 ne contient ni stdint.hni cstdint.

  3. Les implémentations de cstdintsont pour la plupart simplement #include <stdint.h>avec quelques corrections d'espace de noms / de langue.

moteur de haine
la source
2
3. est faux. cstdintdoit hisser les implémentations dans l'espace de noms std.
Konrad Rudolph
1
1. est également faux, stdint.h est défini comme faisant partie de la bibliothèque C ++ dans l'annexe normative D du standard C ++.
détendre
@chill, pourriez-vous s'il vous plaît fournir un lien vers l'annexe D? Ici, en.cppreference.com/w/cpp/types/integer a déclaré qu'il s'agissait d'un en- tête C ++ 11.
hate-engine
1
@ hate-engine, je vous suggère de le rechercher dans votre copie du standard C ++. Cette page de référence ne mentionne pas stdint.h. Il n'y a pas d'argument qui cstdintsoit un en-tête C ++.
détendre
2
Aucune partie de 1. n'est fausse, c'est juste que, pris ensemble, il semble que vous dites stdint.hne pas faire partie de C ++ 11. En fait, il est requis par C ++ 11. Vous pourriez dire, " intest en C ++ 11; longest en C99; C et C ++ sont des langages différents!", Et aucune partie de cela ne serait fausse non plus. Mon exemple est encore plus trompeur, cependant, puisque C ++ 11 se réfère en partie à C99 pour définir le contenu des deux stdint.het cstdint, mais ne fait pas référence à C pour définir int.
Steve Jessop