Что такое uint_fast32_t и почему его следует использовать вместо обычных int и uint32_t?

110

Таким образом, причина для typedefпримитивных типов данных: ed заключается в том, чтобы абстрагироваться от низкоуровневого представления и облегчить понимание ( uint64_tвместо long longтипа, который составляет 8 байтов).

Однако uint_fast32_tесть такой же, typedefкак uint32_t. Сделает ли использование «быстрой» версии программу быстрее?

Амуму
источник
long long может быть не 8 байтов, возможно иметь long long с 1 байтом (в случае, если CHAR_BIT не менее 64) или с 3738383 байтами. также uint64_t может быть 1,2,4 или 8 байтов, для этого CHAR_BIT должен быть 64, 3, 16 или 8.
12431234123412341234123

Ответы:

135
  • intна некоторых платформах может быть всего 16 бит. Для вашего приложения этого может быть недостаточно.
  • uint32_tне гарантируется существование. Необязательно typedef, чтобы реализация была предоставлена, если она имеет беззнаковый целочисленный тип ровно 32 бита. Например, у некоторых есть 9-битные байты, поэтому у них нет файла uint32_t.
  • uint_fast32_tчетко заявляет о ваших намерениях: это тип минимум 32 бита, который является лучшим с точки зрения производительности. uint_fast32_tна самом деле может быть 64 бита. Все зависит от реализации.

... есть тот, uint_fast32_tкоторый имеет тот же typedef, что и uint32_t...

То, что вы смотрите, не является стандартом. Это конкретная реализация (BlackBerry). Таким образом, вы не можете вывести оттуда то uint_fast32_tже самое, что и uint32_t.

Смотрите также:

Яков Галка
источник
36
Хороший ответ. Для полноты картины можно было бы также указать на разницу uint_least32_t, которая такая же, как uint_fast32_tза исключением того, что предпочитает меньший магазин, а не скорость.
Дэймон
2
Почему самое быстрое целое число с шириной не менее 32 бита должно быть больше 32 бита? Я всегда думал, что если будет меньше бит, будет меньше бит, над которыми должен работать процессор, а значит, быстрее. Что мне здесь не хватает?
Шейн Сюй
12
@ShaneHsu: скажем, у 64-битного процессора будет 64-битное лето, которое суммирует 64-битные числа за один цикл. Неважно, хотите ли вы работать только с 32-битными числами, это не будет быстрее одного цикла. Теперь, хотя это не так на x86 / amd64, 32-битные целые числа могут быть даже не адресуемыми. В таком случае работа с ними требует дополнительных операций для извлечения 32-битных, скажем, 64-битных выровненных блоков. См. Также связанный вопрос. Стандарт C ++ написан так, чтобы он мог работать на машине, имеющей 37-битные слова ... так что 32-битного типа там вообще нет.
Яков Галка
42

Отличие заключается в их точности и доступности.

Док здесь говорит:

целочисленный тип без знака с шириной ровно 8, 16, 32 и 64 бит соответственно ( предоставляется только в том случае, если реализация напрямую поддерживает тип ):

uint8_t
uint16_t
uint32_t
uint64_t

И

самый быстрый беззнаковый целочисленный тип без знака с шириной не менее 8, 16, 32 и 64 бит соответственно

uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t    

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

С другой стороны, uint_fast32_tэто тип, который имеет как минимум 32 бита, что также означает, что реализация может typedef, uint32_tкак uint_fast32_t если бы она обеспечивала uint32_t. Если он не предоставляет uint32_t, то это uint_fast32_tможет быть typedef любого типа, который имеет хотя бы 32биты.

Наваз
источник
3
Но какова причина того, что, например, uint_fast32_t быстрее, чем uint32_t? Почему быстрее?
Destructor
2
@PravasiMeet: Не все целые числа доступны одинаково. К некоторым легче получить доступ, чем к другим. Проще означает меньше вычислений, более прямой, что приводит к более быстрому доступу. Теперь uint32_tточно 32-битный во всех системах (если он существует), что может быть не быстрее по сравнению с, скажем, 64-битным. uint_fast32_tс другой стороны, как минимум 32-битный, может быть даже 64-битный.
Nawaz
10
@Destructor: на некоторых процессорах, если переменная сохраняется в регистре, который длиннее, компилятору, возможно, придется добавить дополнительный код для отсечения лишних битов. Например, если он uint16_t x;сохраняется в 32-битном регистре ARM7-TDMI, код x++;может быть оценен как x=((x+1)<<16)>>16);. В компиляторах для этой платформы, uint_fast16_tскорее всего, будет определен как синоним, uint32_tчтобы избежать этого.
supercat 07
почему тоже [u]int_(fast|least)N_tне являются необязательными? Разумеется, стандарт не требует, чтобы все архитектуры поддерживали примитивные типы размером не менее 64 бит? Однако формулировка stdint.hподразумевает, что они должны. Мне кажется странным, что мы добиваемся этого с 1999 года, за несколько лет до того, как 64-битные вычисления стали мейнстримом, не говоря уже об отставании от этого (во многих случаях все еще текущего) встроенных архитектур. Мне это кажется большой оплошностью.
underscore_d
1
@underscore_d: например, нет особой причины, по которой Стандарт не может быть применим к реализации PIC12 с 16 байтами ОЗУ данных и пространством для 256 инструкций. Такая реализация должна отклонить множество программ, но это не должно мешать ей вести себя определенным образом для программ, потребности которых она может удовлетворить.
supercat
4

Находясь #include inttypes.hв своей программе, вы получаете доступ к множеству различных способов представления целых чисел.

Тип uint_fast * _t просто определяет самый быстрый тип для представления заданного количества бит.

Подумайте об этом так: вы определяете переменную типа shortи несколько раз используете ее в программе, что совершенно верно. Однако система, над которой вы работаете, может работать быстрее со значениями типа int. Определяя переменную как тип uint_fast*t, компьютер просто выбирает наиболее эффективное представление, с которым он может работать.

Если между этими представлениями нет никакой разницы, тогда система выбирает то, что ей нужно, и последовательно использует его.

Харли Шугерман
источник
9
Почему inttypes.h, а не stdint.h? Кажется, что inttypes.h содержит только различную, в меру полезную ерунду, плюс включение stdint.h?
Lundin
@underscore_d Я знаю разницу. Но кто использует stdio.h в профессиональных программах, вне зависимости от области применения?
Lundin
@Lundin Я понятия не имею, кто они такие и существуют ли они! Я просто подумал, что было бы полезно предоставить ссылку, разъясняющую, что это за «в меру полезный вздор» ;-) Возможно, это поможет людям понять, что вы правы, и им это не нужно.
underscore_d
-1

Обратите внимание, что быстрая версия может быть больше 32 бит. Хотя быстрый int хорошо впишется в регистр, будет выровнен и тому подобное: но он будет использовать больше памяти. Если у вас их большие массивы, ваша программа будет работать медленнее из-за большего количества обращений к кешу памяти и пропускной способности.

Я не думаю, что современный CPUS выиграет от fast_int32, поскольку обычно знак, расширяющийся с 32 до 64 бит, может произойти во время инструкции загрузки, и идея о том, что существует «родной» целочисленный формат, который работает быстрее, устарела.

Гил Колгейт
источник