Любые гарантированные минимальные размеры для типов в C? - PullRequest
12 голосов
/ 15 ноября 2009

Можете ли вы вообще сделать какие-либо предположения о минимальном размере типа данных?

Что я прочитал до сих пор:

  • char: 1 байт
  • short: 2 байта
  • int: 2 байта, обычно 4 байта
  • long: 4 байта

флоат ??? двойной ???

Являются ли значения в float.h и limits.h системно-зависимыми?

Ответы [ 9 ]

30 голосов
/ 15 ноября 2009

Это описано в статье Википедии :

A short int не должно быть больше int.
int не должно быть больше long int.

A short int должно иметь длину не менее 16 бит.
int должен иметь длину не менее 16 бит.
* long int должен иметь длину не менее 32 бит.
* long long int должен иметь длину не менее 64 бит.

Стандарт не требует, чтобы какой-либо из этих размеров был обязательно другим. Например, это совершенно справедливо, если все четыре типа имеют длину 64 бита.

11 голосов
/ 15 ноября 2009

Да, значения в float.h и limits.h зависят от системы. Вы никогда не должны делать предположений о ширине типа, но стандарт устанавливает некоторые минимумы. См. §6.2.5 и §5.2.4.2.1 в C99 стандарте .

Например, стандарт только говорит, что char должно быть достаточно большим, чтобы вместить каждый символ в наборе символов выполнения. Он не говорит, насколько он широк.

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

§6.2.5.10

Существует три реальных плавающих типа , обозначенных как float , double и long двойной . 32) Набор значений типа float является подмножеством набора значений типа double ; набор значений типа double является подмножеством набора значений типа long double .

Они неявно определяют, что шире, чем другие, но не конкретно, насколько они широки. «Подмножество» само по себе является неопределенным, поскольку long double может иметь точно такой же диапазон, что и double, и удовлетворять этому условию.

Это довольно типично для C, и многое остается для каждой отдельной среды. Вы не можете предположить, вы должны спросить компилятор.

5 голосов
/ 16 августа 2018

Девять лет и до сих пор нет прямого ответа о размере минимум для float, double, long double.


Любые гарантированные минимальные размеры для типов в C?

Для с плавающей точкой Тип ...

С практической точки зрения, float минимальный размер 32-бит и double * 64-бит . C позволяет double и long double иметь одинаковые характеристики, поэтому long double может быть таким же маленьким, как double. Пример * +1029 * 1 . * * Тысяча тридцать-один

Я мог бы представить, что C-совместимый 48-битный double, возможно, существовал - но не знаю ни одного.


Теперь давайте представим, что наш богатый дядя умер и оставил нам целое состояние, чтобы заплатить за развитие и продвижение культуры за www.smallest_C_float.com .

C указывает:

1) float конечный диапазон составляет не менее [1E-37… 1E + 37]. См FLT_MIN, FLT_MAX

2) (1.0f + FLT_EPSILON) – 1.0f <= 1E-5.

3) float поддерживает положительные и отрицательные значения.

Let X: Digit 1-9
Let Y: Digit 0-9
Let E: value -37 to 36
Let S: + or -
Let b: 0 or 1

Наш float может минимально представлять все комбинации, используя базу 10, SX.YYYYY*10^E.

0.0 и ±1E+37 также необходимы (еще 3). Нам не нужны -0.0, суб-нормали, ± бесконечность или не-числа.

Это 2 * 9 * 10 ^ 5 * 74 + 3 комбинации или 133 200 003, для кодирования которых требуется как минимум 27 битов - каким-либо образом . Напомним, цель минимального размера.

С классическим подходом к основанию 2 мы можем принять подразумеваемую 1 и получить S1.bbbb_bbbb_bbbb_bbbb_b * 2 ^ e или 2 * 2 ^ 17 * 226 комбинаций или 26 бит.

Если мы попробуем основание 16, нам потребуется около 2 * 15 * 16 ^ (4 или 5) * 57 комбинаций или как минимум от 26 до 30 бит.

Вывод: C float требует не менее 26 бит кодирования.


У C double нет необходимости выражать больший экспоненциальный диапазон, чем у float, у него только другое минимальное требование к точности. 1E-9.

S1.bbbb_bbbb_bbbb_bbbb_ bbbb_ bbbb_ bbbb_bb * 2 ^ e -> 2 * 2 ^ 30 * 226 комбинаций или 39 битов.


На нашем представьте, если вы захотите компьютер, мы могли бы иметь 13-битный char и кодировать float, double, long double без заполнения. Таким образом, мы можем реализовать не дополняемые 26-битные float и 39-битные double, long double.


1 : Microsoft Visual C ++ для x86, что делает long двойным синонимом для double

5 голосов
/ 15 ноября 2009

Однако новый C99 определяет (в stdint.h) необязательные типы минимальных размеров, такие как uint_least8_t, int_least32_t и т. Д.
(см. en_wikipedia_Stdint_h )

3 голосов
/ 16 ноября 2009

Если вы не хотите проверять размер (в нескольких символах) любого типа в вашей системе / платформе на самом деле соответствует ожидаемому размеру, вы можете сделать:

enum CHECK_FLOAT_IS_4_CHARS
{
   IF_THIS_FAILS_FLOAT_IS_NOT_4_CHARS = 1/(sizeof(float) == 4)
};
3 голосов
/ 15 ноября 2009

Часто разработчики, задающие подобные вопросы, имеют дело с компоновкой упакованного struct для соответствия определенной структуре памяти (как для протокола сообщений). Предполагается, что язык должен непосредственно указывать расположение 16-, 24-, 32-битных и т. Д. Полей для этой цели.

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

На самом деле язык C не был предназначен для конкретной аппаратной реализации. Как правило, он был задан так, чтобы разработчик компилятора Си мог должным образом адаптироваться к реалиям конкретного процессора. Аппаратная архитектура Франкенштейна, состоящая из 9-битных байтов, 54-битных слов и 72-битных адресов памяти, легко и однозначно сопоставляется с функциями языка Си. (char - 9 бит; short int, int и long int - 54 бита.)

Эта общность объясняет, почему спецификация C говорит что-то вроде «не ожидайте многого о размерах целых чисел, кроме sizeof (char) <= sizeof (short int) <= sizeof (int) <= sizeof (long ИНТ) «. Это означает, что символы могут быть того же размера, что и long! </p>

В настоящее время реальность такова - и будущее, похоже, остается в силе - что программные архитектуры требуют 8-битных байтов, а слова памяти могут быть адресованы как отдельные байты. Это не всегда было так. Не так давно я работал над кибер-архитектурой CDC, которая имеет 6-битные "байты" и 60-битные слова. Реализация C на этом была бы интересна. Фактически, эта архитектура ответственна за странную упаковочную семантику Паскаля - если кто-нибудь помнит это.

2 голосов

C99 N1256 стандартная тяга

http://www.open -std.org / ОТК1 / SC22 / WG14 / WWW / Docs / n1256.pdf

C99 определяет два типа целочисленных гарантий:

  • минимальный размер гарантии
  • относительные размеры между типами

Относительные гарантии

6.2.5 Типы :

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

и 6.3.1.1 Булевы, символы и целые числа определяет относительные ранги преобразования:

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

  • Ранг long long int должен быть больше ранга long int, что должно быть больше, чем ранг int, который должен быть больше, чем ранг короткого int, которое должно быть больше ранга подписанного символа.
  • Ранг любого целого типа без знака должен равняться рангу соответствующего целочисленный тип со знаком, если есть.
  • Для всех целочисленных типов T1, T2 и T3, если T1 имеет больший ранг, чем T2, а T2 имеет более высокий ранг, чем T3, тогда T1 имеет больший ранг, чем T3

Абсолютные минимальные размеры

Упоминается https://stackoverflow.com/a/1738587/895245, вот цитата для удобства.

5.2.4.2.1 Размеры целочисленных типов <limits.h>:

1 [...] Их определяемые реализацией значения должны быть равны или больше по величине (абсолютное значение) показанным [...]

  • UCHAR_MAX 255 // 2 8 - 1
  • USHRT_MAX 65535 // 2 16 - 1
  • UINT_MAX 65535 // 2 16 - 1
  • ULONG_MAX 4294967295 // 2 32 - 1
  • ULLONG_MAX 18446744073709551615 // 2 64 - 1

С плавающей точкой

Если определен макрос __STDC_IEC_559__, то типы IEEE гарантированы для каждого типа C, хотя long double имеет несколько возможностей: Безопасно ли предполагать, что с плавающей запятой IEEE754 представлен в C? 1082 *

1 голос
/ 15 ноября 2009

Цитирование стандарта дает то, что определено как «правильный ответ», но на самом деле оно не отражает то, как программы обычно пишутся.

Люди все время делают предположения, что char равен 8 битам, short равен 16, int равен 32, long равен 32 или 64, а long long равен 64.

Эти предположения не очень хорошая идея, но вас не уволят за их принятие.

Теоретически, <stdint.h> может использоваться для указания типов с фиксированной битовой шириной, но вы должны найти один для Microsoft. ( См. Здесь для MS stdint.h .) Одна из проблем здесь заключается в том, что C ++ технически требуется только совместимость с C89, чтобы быть соответствующей реализацией; даже для простого C C99 не полностью поддерживается даже в 2009 году.

Также неверно утверждать, что для char не указана ширина. Существует, стандарт просто избегает говорить, подписан он или нет. Вот что на самом деле говорит C99:

  • количество бит для наименьшего объекта, который не является битовым полем (в байтах)
    CHAR_BIT 8
  • минимальное значение для объекта со знаком типа char
    SCHAR_MIN -127 // - (2 7 - 1)
  • максимальное значение для объекта со знаком типа char
    SCHAR_MAX +127 // 2 7 - 1
  • максимальное значение для объекта типа unsigned char
    UCHAR_MAX 255 // 2 8 - 1
0 голосов
/ 15 ноября 2009

Большинство библиотек определяют что-то вроде этого:

#ifdef MY_ARCHITECTURE_1
typedef unsigned char u_int8_t;
typedef short int16_t;
typedef unsigned short u_int16_t;
typedef int int32_t;
typedef unsigned int u_int32_t;
typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif

затем вы можете использовать эти typedef в своих программах вместо стандартных типов.

...