Як перевірити, чи визначені цілі числа з фіксованою шириною


25

У C ++ цілі числа з фіксованою шириною визначаються як необов'язкові , але я не можу знайти рекомендований спосіб перевірити, чи вони фактично визначені.

Який би був портативний спосіб перевірити, чи є цілі числа фіксованої ширини?


Там , здається, не буде тест функції макрозйомки , але я припускаю , що ви можете зробити#if defined(INT8_MIN)
Zereges

2
Якщо бібліотека std не забезпечує макрос тестування функцій для цього, ви можете перевірити, чи використовувана вами ланцюжок інструментів забезпечує її чи дозволяє визначити власний тест. Наприклад, CMake дозволяє протестувати певні мовні особливості, компілюючи визначений cppфайл, і залежно від того, чи не вдалося компілювати чи не встановлений макрос, який можна визначити.
t.niese

Якщо ви віддаєте перевагу autoconf для cmake, він має попередньо визначені тести для них. AC_TYPE_INT8_Tпр.
Шон

Якщо хтось має будь-який бал тегів у stdint , IMO cstdint має бути призначений як синонім ( stackoverflow.com/tags/stdint/synonyms ). Я не думаю, що нам потрібні окремі теги C і C ++ для цієї незрозумілої речі; основного тегу в питанні достатньо.
Пітер Кордес

1
@PeterCordes Це спрацювало цього разу: stackoverflow.com/tags/stdint/synonyms
Ендрю Генле

Відповіді:


16

Щоб визначити, чи надається ціле число фіксованої ширини, ви можете перевірити, чи є один із відповідних [U]INT*_MAXабо[U]INT*_MIN макросів.

// may be necessary for your C++ implementation
#define __STDC_LIMIT_MACROS 
#include <cstdint>

#ifdef INT32_MAX
// int32_t must be available to get here
int32_t some32bitIntVariable;
#endif

За 7,20 типів цілих чисел<stdint.h> , пункт 4 стандарту C11 (зверніть увагу на напівжирні частини):

Для кожного типу, описаного в цьому документі, який надає реалізація, слід <stdint.h>оголосити це typedefім'я та визначити пов'язані макроси . І навпаки, для кожного описаного тут типу, який реалізація не надає, <stdint.h>не слід оголошувати це typedefім'я не повинно а також не визначати пов'язані макроси .

C ++ успадковує реалізацію C через <cstdint>. Дивіться <cstdint>vs<stdint.h> для отримання детальної інформації. Також див. Що __STDC_LIMIT_MACROSі що __STDC_CONSTANT_MACROSозначає?для детальної інформації про __STDC_LIMIT_MACROS.

Таким чином, якщо int32_tвона є, INT32_MAXі INT32_MINповинна бути #defined. І навпаки, якщо int32_tнемає, ні, INT32_MAXніINT32_MIN дозволено бути #define«д.

Зауважте, що, як заявлено @NicolBolas в іншій відповіді , перевірити це, можливо, не потрібно.


Буде коротше перевірити [U]INT*_Cзамість макросів min та max
phuclv

1
@phuclv За винятком того, що це не те саме. Наприклад INT64_C, визначається, якщо int64_least_tє, а не, якщо int64_tє. Зверніться до документації
Гонки легкості в орбіті

19

В цілому ... ви цього не робите.

Якщо вам потрібно використовувати цілі типи фіксованого розміру, то це означає, що вам явно потрібно ці типи були певного розміру. Тобто ваш код буде нефункціональним, якщо ви не зможете отримати цілі числа цих розмірів. Тож варто просто їх використовувати; якщо хтось використовує ваш код на компіляторі, якому не вистачає зазначених типів, ваш код не буде компілюватися. Що добре, тому що ваш код не працював, якби він компілювався.

Якщо вам справді не потрібні цілі числа фіксованого розміру, а просто потрібно їх з іншої причини, тоді використовуйте int_least_*типи. Якщо реалізація може надати саме такий розмір, то least_*типи матимуть такий розмір.


4
Це неправда. Я написав прохідні заглушки, які реалізують operator = / etc для платформ, які раніше не підтримують uint8_t. Але для ефективності та налагодження ви не хочете використовувати прохід, якщо це фактично не потрібно.
TLW

@TLW: " Я написав прохідні заглушки, які реалізують operator = / і т. Д. Для платформ, які раніше не підтримують uint8_t. " Добре, але ... чому? Який код ви писали, який повинен бути впевнений, що байт - це 8 біт (імовірно, чому ви використовували uint8_t), але цей код якось повинен був працювати на платформі, де байт не має 8 біт (що, крім використання стара C ++ реалізація, це буде єдиною причиною, чому uint8_tвона не буде доступною)? Тобто, поза сумісністю назад, навіщо вам це потрібно було робити?
Нікол Болас

власність, тому не можу сказати занадто багато. Спільна база даних коду, яка, крім іншого, повинна підтримувати досить вигадливий апаратний стек. uint8_tбуло набагато чіткіше, ніж попередній спеціальний (і часто порушений) підхід.
TLW

Якщо у вас є алгоритм, який виражається, наприклад, у 8-бітових байтах, прохід - це те, що ви можете написати один раз і легко перевірити. Тоді як налаштування кожного місця є тимчасовим і легко виходить непомітно неправильним. O(1)проти O(n)зусиль. З тієї ж причини, чому люди використовують, наприклад uint16_t. Ви запитуєте "чому б не використати uint32_t і не подати його самостійно?", На що відповідь повинна бути очевидною.
TLW

@TLW: "З тієї ж причини, чому люди використовують, наприклад, uint16_t. " Це не моя причина використання uint16_t. Моя причина полягає в тому, що я спілкуюся з пристроєм / форматом / тощо, який розраховує отримати точно 16 біт даних, форматованих у вигляді двійкового, непідписаного цілого числа, використовуючи ендіан для моєї машини, і якщо я не можу отримати тип, який є саме це, то спілкуватися з ним набагато складніше. Моя програма (і API, які я використовую з нею) принципово не можуть працювати на машині, яка цього не забезпечує.
Нікол Болас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.