В чем разница между "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 ответов:
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. Имя typedefuint_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 все остальные типы этой формы являются необязательными.
Из обоснования C99
7.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>
состоит в том, чтобы предоставить набор целочисленных типов , которые определения согласованы между машинами и не зависят от операционные системы и другие особенности реализации . Это определяет, viatypedef
, целочисленные типы различных размеров. Реализация бесплатна к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 бит, экономя место.