Подтвердить что ты не робот

Какая разница между "int" и "int_fast16_t"?

Как я понимаю, в спецификации C указано, что тип int должен быть наиболее эффективным типом на целевой платформе, который содержит не менее 16 бит.

Разве это не то, что тоже означает определение C99 int_fast16_t?

Может быть, они помещают его туда только для согласованности, так как нужны другие int_fastXX_t?

Обновление

Подводя итог обсуждению ниже:

  • Мой вопрос был неправильным во многих отношениях. В стандарте C не указывается битность для int. Он дает диапазон [-32767,32767], который должен содержать.
  • Сначала я понимаю, что большинство людей скажут: "Но этот диапазон подразумевает не менее 16 бит!" Но C не требует двухкомпонентного (или даже двоичного) хранения целых чисел. Если бы они сказали "16-бит", могут быть некоторые платформы с 1-битным четностью, 1-битным знаком и 14-разрядной величиной, которые все еще будут "соответствовать стандарту", ​​но не удовлетворяют этому диапазону.
  • В стандарте ничего не сказано о int, являющемся наиболее эффективным типом. Помимо требований к размеру выше, int может быть определено разработчиком компилятора на основе любых критериев, которые они считают наиболее важными. (скорость, размер, обратная совместимость и т.д.)
  • С другой стороны, int_fast16_t похож на предоставление подсказкам компилятору, что он должен использовать тот тип, который оптимален для производительности, возможно, за счет любого другого компромисса.
  • Аналогично, int_least16_t сообщит компилятору использовать наименьший тип, который >= 16 бит, даже если он будет медленнее. Хорошо для сохранения пространства в больших массивах и т.д.

Пример: MSVC на x86-64 имеет 32-разрядный int, даже в 64-битных системах. MS решила сделать это, потому что слишком много людей предполагали, что int всегда будет ровно 32 бит, и поэтому многие ABI сломаются. Однако возможно, что int_fast32_t будет 64-битным числом, если 64-разрядные значения были бы быстрее на x86-64. (Которое я не думаю, что на самом деле это так, но он просто демонстрирует суть)

4b9b3361

Ответ 1

int_fast16_t гарантированно будет самым быстрым int с размером не менее 16 бит. int не имеет гарантии размера, за исключением того, что:

 sizeof(char) = 1 and sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long).

И что он может содержать диапазон от -32767 до +32767.

(7.20.1.3p2) "Имя typedef int_fastN_t обозначает наивысший тип целочисленного знака с шириной не менее N. Имя typedef uint_fastN_t обозначает наивысший беззнаковый целочисленный тип с шириной не менее N."

Ответ 2

int является "наиболее эффективным типом" в скорости/размере, но это не указано в спецификации C. Это должно быть 16 или более бит.

int_fast16_t - самый эффективный тип скорости с по меньшей мере диапазоном 16 бит int.

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

Пример. В 64-битной машине, где можно было бы иметь int как 64-битный, компилятор может использовать режим с 32-разрядной компиляцией int для обеспечения совместимости. В этом режиме int_fast16_t может быть 64-битным, поскольку это самая быстрая ширина для него, позволяет избежать проблем с выравниванием и т.д.

Ответ 3

Как я понимаю, спецификация C говорит, что тип int должен быть наиболее эффективным типом на целевой платформе, который содержит не менее 16 бит.

В этом стандарте фактически говорится о int: (проект N1570, раздел 6.2.5, параграф 5):

Объект "plain" int имеет натуральный размер, предлагаемый архитектуры среды исполнения (достаточно большой, чтобы содержать любые значение в диапазоне INT_MIN до INT_MAX, как определено в заголовок <limits.h>).

Ссылка на INT_MIN и INT_MAX, возможно, немного вводит в заблуждение; эти значения выбираются на основе характеристик типа int, а не наоборот.

И фраза " натуральный размер" также немного вводит в заблуждение. В зависимости от целевой архитектуры может быть не один "естественный" размер для целочисленного типа.

В другом месте стандарт говорит, что INT_MIN должен быть не более -32767, а INT_MAX должен быть не менее +32767, что означает, что int составляет не менее 16 бит.

Вот что говорит стандарт о int_fast16_t (7.20.1.3):

Каждый из следующих типов обозначает целочисленный тип, который обычно быстрее всего работать со всеми целыми типами, которые имеют по крайней мере указанная ширина.

со сноской:

Назначенный тип не гарантируется как самый быстрый для всех целей; если в реализации нет четких оснований для выбора одного типа другой, он просто выберет некоторый целочисленный тип, удовлетворяющий требования к подписке и ширине.

Требования для int и int_fast16_t аналогичны, но не идентичны - и они также смутно.

На практике размер int часто выбирается на основе критериев, отличных от "естественного размера", или эта фраза интерпретируется для удобства. Часто размер int для новой архитектуры выбирается так, чтобы соответствовать размеру для существующей архитектуры, чтобы свести к минимуму трудность переноса кода. И есть достаточно сильная мотивация сделать int не более 32 бит, так что типы char, short и int могут охватывать размеры 8, 16 и 32 бит. В 64-битных системах, в частности x86-64, "естественный" размер, вероятно, составляет 64 бита, но большинство компиляторов C составляют int 32 бита, а не 64 (а некоторые компиляторы даже делают long всего 32 бита).

Выбор базового типа для int_fast16_t, как я подозреваю, в меньшей степени зависит от таких соображений, поскольку любой его код явно запрашивает быстрый 16-разрядный целочисленный тип со знаком. Много существующего кода делает предположения о характеристиках int, которые выходят за рамки стандартных гарантий, а разработчики компилятора должны обслуживать такой код, если они хотят, чтобы их компиляторы использовались.

Ответ 4

Различие заключается в том, что быстрым типам разрешено быть более широкими, чем их коллеги (без быстрого) для целей оптимизации/оптимизации. Но стандарт C ни в коем случае не гарантирует, что они на самом деле быстрее.

C11, 7.20.1.3 Самые быстрые целые числа минимальной ширины

1 Каждый из следующих типов обозначает целочисленный тип, который обычно быстрее всего 262) для работы со всеми целыми типами, которые имеют по крайней мере, указанной ширины.

2 Имя typedef int_fastN_t обозначает самое быстрое целое число со знаком тип с шириной не менее N. Имя typedef uint_fastN_t обозначает наивысший беззнаковый целочисленный тип с шириной не менее Н.

262) Назначенный тип не гарантируется как самый быстрый для всех цели; если в реализации нет четких оснований для выбора один тип над другим, он просто выберет некоторый целочисленный тип удовлетворяющих требованиям подписи и ширины.

Другое отличие состоит в том, что требуются быстрые и наименьшие типы типов, тогда как другие точные типы ширины являются необязательными:

3 Требуются следующие типы: int_fast8_t int_fast16_t int_fast32_t int_fast64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t Все остальные типы этой формы являются необязательными.

Ответ 5

Из соображения C99 7.8 Преобразование формата целых типов <inttypes.h> (документ, сопровождающий стандарт), подчеркивание мое:

C89 указывает, что язык должен поддерживать четыре подписанных и беззнаковые целочисленные типы данных, char, short, int и long, но места очень мало требований к их размеру , кроме этого int и short be не менее 16 бит и long должны быть как минимум до тех пор, пока int и не меньше чем 32 бит. Для 16-битных систем большинство реализаций назначают 8, 16, 16 и 32 бит до char, short, int и long соответственно. Для 32-битных систем, распространенной практикой является назначение 8, 16, 32 и 32 бит для эти типы. Эта разница в размере int может создать некоторые проблемы для пользователи, которые переходят из одной системы в другую, которая назначает разные размеры до целочисленных типов, поскольку правило стандартного Cs для целых чисел может неожиданно произвести бесшумные изменения. Необходимость определения расширенный целочисленный тип увеличился с введением 64-битного системы.

Цель <inttypes.h> - предоставить набор целых типов , определения согласованы между машинами и не зависят от операционных систем и других особенностей реализации. Он определяет, через typedef, целые типы различных размеров. Реализации бесплатны до typedef их как стандартных типов или расширений C, которые они поддержка. Последовательное использование этого заголовка значительно увеличит переносимость пользовательской программы на разных платформах.

Основное различие между int и int_fast16_t заключается в том, что последний, вероятно, будет свободен от этих "особенностей реализации". Вы можете подумать об этом как о чем-то вроде:

Мне не нужна текущая ОС/реализация "политика" размера int. Просто дайте мне любой самый быстрый тип целочисленного знака с не менее 16 битами.

Ответ 6

На некоторых платформах использование 16-разрядных значений может быть намного медленнее, чем использование 32-битных значений [например. для 8-битного или 16-разрядного хранилища потребуется выполнить 32-разрядную нагрузку, модифицировать загруженное значение и записать результат]. Даже если в кэше можно было бы в два раза больше 16-битных значений в виде 32-битных значений (нормальная ситуация, когда 16-битные значения были бы быстрее 32-битных значений в 32-разрядных системах), необходимо иметь каждую запись которому предшествует чтение, отрицает любое преимущество скорости, которое может возникнуть, если структура данных не была прочитана гораздо чаще, чем она была написана. На таких платформах тип типа int_fast16_t, вероятно, будет 32 бита.

Что, как было сказано, стандарт, к сожалению, не позволяет использовать наиболее полезную семантику для компилятора, которая должна была бы разрешать переменные типа int_fast16_t, адрес которых не принимается, чтобы произвольно вести себя как 16-битные типы или более крупные типы, в зависимости от того, что удобно. Рассмотрим, например, метод:

int32_t blah(int32_t x)
{
  int_fast16_t y = x;
  return y;
}

На многих платформах 16-разрядные целые числа, хранящиеся в памяти, часто можно манипулировать так же, как и те, которые хранятся в регистрах, но нет инструкций для выполнения 16-разрядных операций с регистрами. Если переменная int_fast16_t, хранящаяся в памяти, может содержать только -32768 до +32767, это же ограничение применимо к переменным int_fast16_t, хранящимся в регистрах. Поскольку принудительное увеличение негабаритных значений в виде целочисленных типов со знаком, слишком малым, чтобы их удерживать, является поведение, определяемое реализацией, которое заставило бы приведенный выше код добавлять команды для подписывания более ранних 16 бит x перед его возвратом; если Стандарт разрешен для такого типа, гибкий "по меньшей мере 16 бит, но более удобный" тип может устранить необходимость в таких инструкциях.

Ответ 7

Пример того, как два типа могут быть разными: предположим, что архитектура - это архитектура, где 8-разрядная, 16-разрядная, 32-битная и 64-разрядная арифметика одинаково быстры. (I386 близок.) Затем разработчик может использовать модель LLP64 или, еще лучше, позволить программисту выбирать между ILP64, LP64 и LLP64, поскольку существует много кода, который предполагает, что он длится ровно 32 бита, и что sizeof(int) <= sizeof(void*) <= sizeof(long). Любая 64-битная реализация должна нарушать хотя бы одно из этих допущений.

В этом случае int, вероятно, будет иметь ширину в 32 бита, потому что это сломает наименьший код из других систем, но uint_fast16_t все равно может быть 16 бит в ширину, экономя пространство.