<cstdint> против <stdint.h>

97

В чем разница между stdint.hи cstdint?

Оба они доступны в MSVC (Visual Studio 2010) и gcc-4.5.1. Также оба определяют intX_t/ uintX_tтипы (где Xразмер в байтах типа).

  • Если обоснование в обоих заголовках одинаково (переносимые типы), какие решения я должен принять, чтобы выбрать тот или другой?

В stdint.hопределяет каждый тип без какого-либо пространства имен, cstdintтипы лежат в stdпространстве имен.

  • Есть ли причина включать или не включать определенные типы в stdпространство имен? Чем отличаются эти два заголовка?

cstdintне имеет расширения файла и использует cпрефикс, stdint.hиспользует .hрасширение.

  • Каковы соглашения об именах для этих заголовков? cпрефикс указывает на то, что это библиотека C? есть причина отсутствия расширения файла в cstdint?
PaperBirdMaster
источник
OS X 10.8 не хватает <cstdint>. Вот ошибка я получаю: ./misc.h:7:10: fatal error: 'cstdint' file not found.
jww 08

Ответы:

124

Первоначальное намерение C ++ 98 состояло в том, что вы должны использовать <cstdint>C ++, чтобы избежать загрязнения глобального пространства имен (ну, не <cstdint>в частности, это добавлено только в C ++ 11, но <c*>заголовки в целом).

Однако реализации все равно продолжали помещать символы в глобальное пространство имен, и C ++ 11 одобрил эту практику [*]. Итак, у вас в основном есть три варианта:

  • Используйте <cstdint>и либо полностью квалифицируйте каждый используемый вами целочисленный тип, либо добавьте его в область видимости с помощью и using std::int32_t;т. Д. (Раздражает, потому что многословен, но это правильный способ сделать это, как и для любого другого символа в стандартной библиотеке C ++)
  • Использование <stdint.h>(немного плохо, потому что устарело)
  • Используйте <cstdint>и предполагайте, что ваша реализация поместит символы в глобальное пространство имен (очень плохо, потому что не гарантируется).

На практике я подозреваю, что раздражающий большой объем кода использует последний вариант просто потому, что это легко сделать случайно в реализации, в которой <cstdint>символы помещаются в глобальное пространство имен. Вы должны попробовать использовать первое. У второго есть одно достоинство: он гарантированно помещает что-то в глобальное пространство имен, а не только, возможно, делает это. Я не думаю, что это особенно полезно, но это может сэкономить немного времени на вводе текста, если это ваш приоритет.

Есть четвертый вариант, #include <cstdint>за using namespace std;которым иногда бывает полезно, но есть места, куда не следует помещать using namespace std;. У разных людей разные представления о том, где находятся эти места, но «на верхнем уровне в файле заголовка» хуже, чем «на верхнем уровне в файле cpp», что хуже, чем «в ограниченном объеме». Некоторые люди using namespace std;вообще никогда не пишут .

[*] Это означает, что стандартные заголовки C ++ могут помещать данные в глобальное пространство имен, но не обязательны. Таким образом, вы должны избегать столкновения с этими символами, но вы не можете их использовать, потому что их может не быть. По сути, глобальное пространство имен в C ++ - это минное поле, старайтесь его избегать. Кто-то может возразить, что комитет ратифицировал практику реализации, которая почти так же вредна, как закрепление using namespace std;на верхнем уровне в файле заголовка - разница в том, что реализации делают это только для символов в стандартной библиотеке C, тогда using namespace std;как для C ++. -только символы. В стандарте C есть раздел, в котором перечислены имена, зарезервированные для будущих дополнений к стандарту. Считать эти имена зарезервированными и в глобальном пространстве имен C ++ - не совсем глупая идея, но это не обязательно.

Стив Джессоп
источник
Единственный остающийся без ответа вопрос касается соглашений об именах файлов заголовков, знаете ли вы об этой теме?
PaperBirdMaster
24
@PaperBirdMaster: C ++ стандартных заголовков библиотек не имеют расширений файлов: <iostream>, <vector>, <cstdlib>, кроме тех , которые включены для обеспечения совместимости C: <stdint.h>, <stdlib.h>. И да, начальная буква cуказывает на то, что она <cstdlib>является эквивалентом C ++ стандартного заголовка C <stdlib.h>, а не является полностью новым для C ++, как <vector>есть. Есть заголовок C ++ <complex>, поэтому нам остается только надеяться, что ни в одной будущей версии C не будет стандартного заголовка <omplex.h>.
Стив Джессоп,
@SteveJessop Erm, C99?
SS Anne
1
@ JL2210 заметил, что он сказал <omplex.h>, что нет <complex.h>. Если добавить <omplex.h>C, эквивалент C ++ будет <complex>.
John Leuenhagen
16

Включение cstdintимпортирует имена символов в пространство имен std и, возможно, в глобальное пространство имен.
Включение stdint.hимпортирует имена символов в глобальное пространство имен и, возможно, в пространство имен std.

Возможности стандартной библиотеки C также предоставляются в стандартной библиотеке C ++, и в качестве общего соглашения об именах они добавляются к соответствующим именам в стандартной библиотеке C.

В C ++ вы должны использовать:

#include <cstdint>

и полностью уточните имена символов, которые вы используете std::
в C, вы должны использовать:

#include <stdint.h>

В приложении D (нормативное) Характеристики совместимости [depr] говорится:

D.6 Заголовки стандартной библиотеки C

1 Для совместимости со стандартной библиотекой C и C Unicode TR стандартная библиотека C ++ предоставляет 25 заголовков C, как показано в таблице 151.

Который включает в себя:

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

И далее,

2 Каждый заголовок C, каждый из которых имеет имя формы name.h, ведет себя так, как если бы каждое имя, помещенное в пространство имен стандартной библиотеки соответствующим cname header, помещалось в область глобального пространства имен. Не указано, были ли эти имена сначала объявлены или определены в области видимости пространства имен (3.3.6) пространства имен std, а затем введены в глобальную область пространства имен явными объявлениями using (7.3.3).

3 [Пример: заголовок, <cstdlib>несомненно, предоставляет свои объявления и определения в пространстве имен std. Он также может предоставлять эти имена в глобальном пространстве имен. Заголовок, <stdlib.h>несомненно, предоставляет те же объявления и определения в глобальном пространстве имен, как и в стандарте C. Он также может предоставлять эти имена в пространстве имен std. —Конечный пример]

Алок Сохранить
источник
-1
  1. cstdintэто заголовок C ++ 11, заголовок stdint.hC99 (C и C ++ - разные языки!)

  2. MSVC 2008 не содержит ни, stdint.hни cstdint.

  3. Реализации в cstdintосновном просто #include <stdint.h>с некоторыми исправлениями пространства имен / языка.

двигатель ненависти
источник
2
3. неправильно. cstdintнеобходимо поднять реализации в пространство имен std.
Конрад Рудольф
1
1. тоже неверно, stdint.h определен как часть библиотеки C ++ в нормативном Приложении D стандарта C ++.
chill
@chill, не могли бы вы дать ссылку на Приложение D? Здесь en.cppreference.com/w/cpp/types/integer указано, что это заголовок C ++ 11.
hate-engine
1
@ hate-engine, я предлагаю вам найти его в своей копии стандарта C ++. Эта страница cppreference не упоминает stdint.h. Нет аргумента, что cstdintэто заголовок C ++.
chill
2
Никакая часть 1. не является ложной, просто все вместе выглядит так, как будто вы говорите, что stdint.hона не является частью C ++ 11. Фактически этого требует C ++ 11. Вы могли бы сказать: « intнаходится на C ++ 11; longнаходится на C99; C и C ++ - разные языки!», И это тоже не будет ложным. Однако мой пример еще более вводит в заблуждение, поскольку C ++ 11 частично ссылается на C99 для определения содержимого обоих stdint.hи cstdint, но не ссылается на C для определения int.
Стив Джессоп,