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

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

разве это не то, что определение c99 int_fast16_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-бит, и поэтому много ABIs сломался бы. Однако, возможно, что 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. На имя 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):

"простой" int


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

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

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

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

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

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

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


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

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