Uint32_t vs uint_fast32_t vs uint_least32_t

Я видел различные типы определения целого числа в stdint.h. Я приведу в качестве примера 32-битное целое число без знака.

  • uint32_t означает четное целое число без знака 32 бита. Это тот, который я всегда использую.

  • uint_fast32_t и uint_least32_t: Какая разница с uint32_t и когда я должен использовать их вместо uint32_t?

И теперь я увидел uintX_t, где X - 24, 40, 48 и 56. В моем коде бывает, что я должен работать с 48 и 56-битными целыми числами. В качестве примера, я полагаю, что uint24_t определяется как нечто подобное:

struct uint24_t { unsigned int the_integer : 24; };

Я прав? И предложите ли вы мне использовать uint48_t для моих 48-битных целых чисел без знака или я должен использовать обычный uint64_t?

Спасибо за ваши объяснения.

Ответы

Ответ 1

какая разница с uint32_t

uint_fast32_t представляет собой неподписанный тип, по меньшей мере, 32 бита, который (каким-то общим способом) является самым быстрым из таких типов. "быстрый" означает, что, учитывая выбор, разработчик, вероятно, будет выбирать размер, для которого у архитектуры есть арифметические, нагрузка и сохранение инструкций. Это не победитель какого-либо конкретного теста.

uint_least32_t - наименьший неподписанный тип не менее 32 бит.

uint32_t - это тип ровно 32 бит без заполнения, если такой тип существует.

Я прав?

Нет. Если uint24_t существует вообще, то это целочисленный тип, а не struct. Если в этой реализации нет целочисленного типа без знака 24 бита, он не существует.

Поскольку unsigned long требуется как минимум 32 бита, единственными стандартными типами, которые uint24_t могли бы быть когда-либо псевдонимом, являются char, unsigned char, unsigned short и unsigned int. В качестве альтернативы это может быть расширенный тип (то есть целочисленный тип, предоставляемый реализацией, который не является одним из определенных целочисленных типов в стандарте).

Вы предложите мне использовать uint48_t для моих 48-разрядных целых чисел без знака?

Если он существует и является желаемым, вы можете его использовать. Однако он не будет существовать на очень многих реализациях, поэтому он подходит только для использования в переносном коде. Это ОК обеспечило причину, по которой вам приходится иметь дело с точными 48-битными целыми, зависит от платформы.

Точные 16, 32 и 64-битные типы также являются технически необязательными, но они должны существовать, если реализация имеет подходящие целочисленные типы. "Подходящий" означает не только то, что существует точный N-разрядный неподписанный тип без битов заполнения, но также и то, что соответствующий подписанный тип не имеет заполняющих битов и использует 2 дополнительных представления. На практике это настолько близко, что вы ограничиваете переносимость очень мало, используя любой из них. Для максимальной переносимости вы должны использовать uint_least32_t или uint_fast32_t, предпочитая uint32_t. Какая из них зависит от того, будете ли вы больше заботиться о скорости или размере. По моему опыту очень мало людей беспокоятся, поскольку платформы, у которых нет 32-битного целочисленного типа, уже настолько странны, что большинство людей не заботятся о том, работает ли на них свой код или нет.

Ответ 2

uint32_t существует только в том случае, если платформа поддерживает неподписанный интегральный тип шириной всего 32 бита и не имеет дополнения.

uint32_least_t всегда существует и является неподписанным интегральным типом с не менее чем 32 битами, и он является наименьшим таким типом.

uint32_fast_t также всегда существует и является интегральным типом с не менее чем 32 битами, и это "самый естественный" тип для платформы, то есть тип, для которого операции генерируют наиболее эффективный код.

Примечание. Подписанная версия int32_t также требует представления 2 дополнений.