Как проверить, определены ли целые числа фиксированной ширины

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>против<stdint.h> некоторых деталей. Также смотрите Что __STDC_LIMIT_MACROSи что __STDC_CONSTANT_MACROSзначит? для деталей о __STDC_LIMIT_MACROS.

Таким образом, если int32_tдоступно, INT32_MAXи INT32_MINдолжно быть #define'd. И наоборот, если int32_tнет в наличии, ни то, INT32_MAXни другое не INT32_MINможет быть #define'd.

Заметьте, однако, что, как @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 = / etc для платформ, которые раньше не поддерживают 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, которые я использую с ней) принципиально не может функционировать на машине, которая этого не обеспечивает.
Никол Болас