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


95

У чому різниця між 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?

Не вистачає OS X 10.8 <cstdint>. Ось помилка я отримую: ./misc.h:7:10: fatal error: 'cstdint' file not found.
jww

Відповіді:


122

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

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

  • Використовуйте <cstdint>і повністю кваліфікуйте кожен цілий тип, який ви використовуєте, або вводьте його в область дії за допомогою using std::int32_t;etc (дратує, тому що це багатослівно, але це правильний спосіб зробити це так само, як і для будь-якого іншого символу в стандартній бібліотеці 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 ++ -Тільки символи теж. У стандарті С є розділ, в якому перелічені імена, зарезервовані для майбутніх доповнень до стандарту. Не зовсім дурна ідея також розглядати ці імена як зарезервовані в глобальному просторі імен С ++, але це не принципово.


Єдине питання, що залишається без відповіді, - це питання про правила іменування файлів заголовків, чи знаєте ви про цю тему?
PaperBirdMaster

24
@PaperBirdMaster: C ++ стандартних заголовків бібліотек не мають розширень файлів: <iostream>, <vector>, <cstdlib>, крім тих , які включені для забезпечення сумісності C: <stdint.h>, <stdlib.h>. І так, початковий символ cвказує, що <cstdlib>це еквівалент C ++ стандартного заголовка C <stdlib.h>, а не є цілком новим для C ++, як <vector>є. Є заголовок С ++ <complex>, тому нам залишається сподіватися, що жодна майбутня версія С не вводить стандартний заголовок <omplex.h>.
Steve Jessop

@SteveJessop Erm, C99?
SS Anne

1
@ JL2210 зверніть увагу, що він сказав <omplex.h>, ні <complex.h>. Якщо додати <omplex.h>C, еквівалент C ++ буде <complex>.
Джон Лойенгаген,

16

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

Особливості стандартної бібліотеки C також передбачені в стандартній бібліотеці 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, а потім вводяться в глобальну область простору імен за допомогою явних декларацій use (7.3.3).

3 [Приклад: Заголовок <cstdlib>надійно надає свої декларації та визначення в просторі імен std. Він також може надавати ці імена в глобальному просторі імен. Заголовок <stdlib.h>гарантовано надає ті самі декларації та визначення в глобальному просторі імен, як і в Стандарті C. Він також може надавати ці імена в просторі імен std. —Кінцевий приклад]


-1
  1. cstdintє заголовком C ++ 11, stdint.hє заголовком C99 (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, чи можете ви надати посилання на Додаток D? Тут en.cppreference.com/w/cpp/types/integer зазначив, що це заголовок C ++ 11.
hate-engine

1
@ hate-engine, пропоную пошукати його у своїй копії стандарту C ++. Ця сторінка cppreference не згадує stdint.h. Немає жодного аргументу, який cstdintє заголовком на C ++.
холод

2
Жодна частина 1. не є хибною, просто в сукупності виглядає так, ніби ви говорите stdint.h, що не є частиною C ++ 11. Насправді це вимагається C ++ 11. Можна сказати, " intє на C ++ 11; longє на C99; C і C ++ - це різні мови!", І жодна частина цього також не буде хибною. Мій приклад, однак, ще більш оманливий, оскільки C ++ 11 частково посилається на C99 для визначення вмісту обох stdint.hі cstdint, але не посилається на C для визначення int.
Steve Jessop
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.