В чем разница между "int" и "int fast16 t"?


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

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

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

Обновить

Чтобы подытожить обсуждение ниже:

    Мой вопрос был неправильным во многих отношениях. Стандарт C не определяет разрядность for 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. (Я не думаю, что это действительно так, но это просто демонстрирует точку зрения)

7 36

7 ответов:

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."

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

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

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

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

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

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

A "равнина" 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, которые выходят за рамки того, что гарантирует стандарт, и разработчики компиляторов должны учитывать такой код, если они хотят, чтобы их компиляторы использовались.

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

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

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

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

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 все остальные типы этой формы являются необязательными.

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

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

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

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

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

На некоторых платформах использование 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, хранящимся в регистрах. Поскольку принудительное преобразование больших значений в целочисленные типы со знаком, слишком маленькие для их хранения, является поведением, определяемым реализацией, это вынудило бы приведенный выше код добавить instructions to sign-расширение нижних 16 бит x перед его возвратом; если стандарт допускает такой тип, гибкий тип "по крайней мере 16 бит, но больше, если удобно" может устранить необходимость в таких инструкциях.

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

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