<cstdint> vs <stdint.h>

В чем разница между 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?

Ответы

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

#include <cstdint>

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

#include <stdint.h>

Приложение D (нормативное) Особенности совместимости [des]:

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

1 Для совместимости со стандартной библиотекой C и C Unicode TR стандартная библиотека С++ предоставляет заголовки 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 и затем будут введены в область глобального пространства имен явным использованием-деклараций (7.3.3).

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

Ответ 3

  • cstdint - заголовок С++ 11, stdint.h - заголовок C99 (C и С++ - разные языки!)

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

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