<cstdint> vs <stdint.h>

97

Jaka jest różnica między stdint.hi cstdint?

Oba są dostępne w MSVC (Visual Studio 2010) i gcc-4.5.1. Oba definiują również intX_t/ uintX_ttypes (gdzie Xjest rozmiarem w bajtach typu).

  • Jeśli uzasadnienie w obu nagłówkach jest takie samo (typy przenośne), jakie decyzje muszę podjąć, aby zdecydować o jednym lub drugim?

stdint.hDefiniuje każdy typ bez nazw, az cstdintrodzaje kłamstw w stdprzestrzeni nazw.

  • Czy jest jakiś powód, aby włączać lub nie uwzględniać zdefiniowanych typów w stdprzestrzeni nazw? Czym się różnią te dwa nagłówki?

cstdintnie ma rozszerzenia pliku i używa cprzedrostka, stdint.hużywa .hrozszerzenia.

  • Jakie są konwencje nazewnictwa dla tych nagłówków? cprzedrostek wskazuje, że jest to biblioteka C? istnieje powód braku rozszerzenia pliku w cstdint?
PaperBirdMaster
źródło
Brakuje OS X 10.8 <cstdint>. Tutaj jest błąd otrzymuję: ./misc.h:7:10: fatal error: 'cstdint' file not found.
jww

Odpowiedzi:

124

Pierwotnym zamiarem C ++ 98 było to, że powinieneś używać <cstdint>w C ++, aby uniknąć zanieczyszczania globalnej przestrzeni nazw (cóż, nie <cstdint>w szczególności, jest to dodawane tylko w C ++ 11, ale <c*>ogólnie w nagłówkach).

Jednak implementacje i tak upierały się przy umieszczaniu symboli w globalnej przestrzeni nazw, a C ++ 11 ratyfikował tę praktykę [*]. Masz więc zasadniczo trzy opcje:

  • Użyj <cstdint>i albo w pełni zakwalifikuj każdy typ liczb całkowitych, którego używasz, albo przenieś go do zakresu za pomocą using std::int32_t;itp. (Irytujące, ponieważ gadatliwe, ale jest to właściwy sposób, aby to zrobić, tak jak w przypadku każdego innego symbolu w standardowej bibliotece C ++)
  • Użycie <stdint.h>(nieco złe, ponieważ wycofane)
  • Użyj <cstdint>i załóż, że Twoja implementacja umieści symbole w globalnej przestrzeni nazw (bardzo źle, ponieważ nie jest to gwarantowane).

W praktyce podejrzewam, że irytująca duża ilość kodu korzysta z ostatniej opcji, po prostu dlatego, że jest to łatwe do zrobienia przez przypadek w implementacji, w której <cstdint>symbole są umieszczane w globalnej przestrzeni nazw. Powinieneś spróbować użyć pierwszego. Drugi ma tę zaletę, że gwarantuje umieszczenie rzeczy w globalnej przestrzeni nazw, a nie tylko może to robić. Nie sądzę, żeby to było szczególnie przydatne, ale może zaoszczędzić trochę pisania, jeśli jest to twój priorytet.

Jest czwarta opcja, #include <cstdint>po using namespace std;której czasami jest przydatna, ale są miejsca, w których nie powinieneś umieszczać using namespace std;. Różni ludzie będą mieli różne pomysły, gdzie te miejsca się znajdują, ale „na najwyższym poziomie w pliku nagłówkowym” jest gorsze niż „na najwyższym poziomie w pliku cpp”, co jest gorsze niż „w ograniczonym zakresie”. Niektórzy using namespace std;w ogóle nie piszą .

[*] Oznacza to, że standardowe nagłówki C ++ mogą umieszczać rzeczy w globalnej przestrzeni nazw, ale nie jest to wymagane. Musisz więc unikać kolizji z tymi symbolami, ale nie możesz ich użyć, ponieważ mogą ich tam nie być. Zasadniczo globalna przestrzeń nazw w C ++ jest polem minowym, staraj się go unikać. Można argumentować, że komitet ratyfikował praktykę poprzez implementacje, która jest prawie tak samo szkodliwa, jak trzymanie się using namespace std;na najwyższym poziomie w pliku nagłówkowym - różnica polega na tym, że implementacje robią to tylko dla symboli w standardowej bibliotece C, podczas gdy using namespace std;robi to dla C ++ -tylko symbole też. W standardzie C jest sekcja, która zawiera listę nazw zarezerwowanych dla przyszłych dodatków do standardu. Nie jest to całkowicie głupi pomysł, aby traktować te nazwy jako zarezerwowane również w globalnej przestrzeni nazw C ++, ale nie jest to konieczne.

Steve Jessop
źródło
Jedyne pytanie bez odpowiedzi, które pozostaje, dotyczy konwencji nazewnictwa plików nagłówkowych, czy znasz ten temat?
PaperBirdMaster
24
@PaperBirdMaster: nagłówki biblioteki standard C ++ nie mają rozszerzenia plików: <iostream>, <vector>, <cstdlib>, oprócz tych zawartych w zgodności C: <stdint.h>, <stdlib.h>. I tak, inicjał cwskazuje, że <cstdlib>jest to odpowiednik C ++ standardowego nagłówka C <stdlib.h>, a nie zupełnie nowy w C ++, jak <vector>jest. Istnieje nagłówek C ++ <complex>, więc musimy mieć tylko nadzieję, że żadna przyszła wersja C nie wprowadzi standardowego nagłówka <omplex.h>.
Steve Jessop
@SteveJessop Erm, C99?
SS Anne
1
@ JL2210 zauważ, że powiedział <omplex.h>, nie <complex.h>. Gdyby dodano C <omplex.h>, odpowiednikiem C ++ byłoby <complex>.
John Leuenhagen,
16

Uwzględnienie cstdintimportuje nazwy symboli w standardowej przestrzeni nazw i prawdopodobnie w globalnej przestrzeni nazw.
Uwzględnienie stdint.himportuje nazwy symboli w globalnej przestrzeni nazw i prawdopodobnie w standardowej przestrzeni nazw.

Funkcje standardowej biblioteki C są również dostępne w C ++ standardowej bibliotece i jako ogólna konwencja nazewnictwa są poprzedzone literą c do odpowiednich nazw w standardowej bibliotece C.

W C ++ powinieneś używać:

#include <cstdint>

iw pełni kwalifikuj nazwy symboli, których używasz std::
w C, powinieneś używać:

#include <stdint.h>

Załącznik D (normatywny) Cechy zgodności [depr] stwierdza:

D.6 Standardowe nagłówki biblioteki C.

1 W celu zapewnienia zgodności ze standardową biblioteką C i C Unicode TR, standardowa biblioteka C ++ udostępnia 25 nagłówków C, jak pokazano w tabeli 151.

Który zawiera:

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

I dalej,

2 Każdy nagłówek C, z których każdy ma nazwę formularza name.h, zachowuje się tak, jakby każda nazwa umieszczona w przestrzeni nazw biblioteki standardowej przez odpowiadającą jej nazwę cname headerzostała umieszczona w zasięgu globalnej przestrzeni nazw. Nie jest określone, czy nazwy te są najpierw zadeklarowane lub zdefiniowane w zakresie przestrzeni nazw (3.3.6) standardowej przestrzeni nazw, a następnie są wprowadzane do globalnego zakresu przestrzeni nazw przez jawne deklaracje using (7.3.3).

3 [Przykład: nagłówek z <cstdlib>pewnością zawiera swoje deklaracje i definicje w ramach standardowej przestrzeni nazw. Może również udostępniać te nazwy w globalnej przestrzeni nazw. Nagłówek z <stdlib.h>pewnością zawiera te same deklaracje i definicje w globalnej przestrzeni nazw, podobnie jak w standardzie C. Może również udostępniać te nazwy w ramach standardowej przestrzeni nazw. - koniec przykładu]

Alok Save
źródło
-1
  1. cstdintto nagłówek C ++ 11, stdint.hto nagłówek C99 (C i C ++ to różne języki!)

  2. MSVC 2008 nie zawiera stdint.hani cstdint.

  3. Implementacje cstdintsą przeważnie #include <stdint.h>z pewnymi poprawkami dotyczącymi przestrzeni nazw / języka.

silnik nienawiści
źródło
2
3. jest źle. cstdintmusi przenieść implementacje do przestrzeni nazw std.
Konrad Rudolph
1
1. jest również błędny, stdint.h jest zdefiniowany jako część biblioteki C ++ w normatywnym załączniku D standardu C ++.
wyluzuj
@chill, czy możesz podać link do załącznika D? Tutaj en.cppreference.com/w/cpp/types/integer stwierdził, że jest to nagłówek C ++ 11.
silnik nienawiści
1
@ Hate-engine, proponuję sprawdzić to w swojej kopii standardu C ++. Ta strona cppreference nie wspomina stdint.h. Nie ma argumentu, który cstdintbyłby nagłówkiem C ++.
chill
2
Żadna część 1. nie jest fałszywa, po prostu razem wygląda na to, że mówisz, że stdint.hnie jest częścią C ++ 11. W rzeczywistości jest to wymagane przez C ++ 11. Można powiedzieć, „ intjest w C ++ 11; longjest w C99; C i C ++ to różne języki!”, Ale żadna część tego też nie byłaby fałszywa. Mój przykład jest jeszcze bardziej mylący, ponieważ C ++ 11 odwołuje się częściowo do C99, aby zdefiniować zawartość obu stdint.hi cstdint, ale nie odwołuje się do C w celu zdefiniowania int.
Steve Jessop