Гарантируется ли `long` как минимум 32 бита? - PullRequest
50 голосов
/ 02 декабря 2010

Изучая стандарт C ++, я всегда понимал, что размеры целочисленных фундаментальных типов в C ++ были следующими:

sizeof(char) <= sizeof(short int) <= sizeof(int) <= sizeof(long int)

Я вывел это из 3.9.1 / 2:

Существует четыре типа целых чисел со знаком: «знаковый символ», «короткое целое», «int» и «длинное целое». В этом списке каждый тип обеспечивает как минимум столько же памяти, сколько предшествует ему в списке.Простые целые имеют естественный размер, предложенный архитектурой среды выполнения

Кроме того, размер char описывается в 3.9.1 / как:

  1. [...] достаточно большой, чтобы хранить любой элемент базового набора символов реализации.

1.7 / 1 определяет это в более конкретных терминах:

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

Это приводитЯ пришел к следующему выводу:

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

, где sizeof говорит нам, сколько байтов имеет тип.Кроме того, это определяется реализацией, сколько битов в байте.Большинство из нас, вероятно, привыкли иметь дело с 8-битными байтами, но в стандарте говорится, что в байте есть n бит.


В этот пост , Альф П.Штейнбах говорит:

long гарантированно (как минимум) 32 бита.

Это бросает вызов всему, что я понимаю, размер фундаментальных типов в C ++ в соответствии со Стандартом.Обычно я просто игнорировал бы это утверждение, поскольку новичок ошибался, но, поскольку это был Альф, я решил, что его стоит продолжить.

Итак, что вы скажете?Гарантируется ли стандарт длиной не менее 32 бит?Если это так, пожалуйста, уточните, как предоставляется эта гарантия.Я просто не вижу этого.

  1. Стандарт C ++ специально говорит, что для того, чтобы знать C ++, вы должны знать C (1.2 / 1) 1

  2. Стандарт C ++ неявно определяет минимальный предел значений, которые long может принять LONG_MIN - LONG_MAX 2

Поэтому, независимо от того, насколько велика long, она должна быть достаточно большой, чтобы удерживать LONG_MIN в LONG_MAX.

Но Альф и другие специфичны , что длинноене менее 32 бит.Это то, что я пытаюсь установить.Стандарт C ++ явно указывает, что число битов в байте не указано (это может быть 4, 8, 16, 42). Так как же соединение устанавливается из возможности размещения чисел LONG_MIN-LONG_MAX до не менее 32 бит??


(1) 1.2 / 1: Следующие ссылочные документы необходимы для применения этого документа.Для датированных ссылок применимо только указанное издание.Для недатированных ссылок применяется самое последнее издание ссылочного документа (включая любые поправки).

  • ИСО / МЭК 2382 (все части), Информационные технологии - Словарь
  • ИСО / МЭК 9899: 1999, Языки программирования - C
  • ISO / IEC 10646-1: 2000, Информационные технологии. Универсальный многооктетный набор кодированных символов (UCS). Часть 1. Архитектура и базовая многоязычная плоскость

(2) Определяется в <climits> как:

LONG_MIN -2147483647 // -(2^31 - 1)
LONG_MAX +2147483647 //   2^31 - 1

Ответы [ 5 ]

36 голосов
/ 02 декабря 2010

C ++ использует ограничения, определенные в стандарте C (C ++: 18.3.2 (c.limits), C: 5.2.4.2.1):

LONG_MIN -2147483647 // -(2^31 - 1)
LONG_MAX +2147483647 //   2^31 - 1

Таким образом, вы гарантированно, что long составляет не менее 32 бит.

И если вы хотите пойти по длинному окольному маршруту, чтобы LONG_MIN / LONG_MAX были представлены long, вам нужно взглянуть на 18.3.1.2 (numeric.limits.members) в стандарте C ++:

static constexpr T min() throw(); // Equivalent to CHAR_MIN, SHRT_MIN, FLT_MIN, DBL_MIN, etc.
static constexpr T max() throw(); // Equivalent to CHAR_MAX, SHRT_MAX, FLT_MAX, DBL_MAX, etc.

Я переместил сноски в комментарий, так что это не совсем то, что указано в стандарте. Но это в основном подразумевает, что std::numeric_limits<long>::min()==LONG_MIN==(long)LONG_MIN и std::numeric_limits<long>::max()==LONG_MAX==(long)LONG_MAX.

Таким образом, хотя стандарт C ++ не определяет побитовое представление (подписанных) отрицательных чисел, он должен либо дополняться двумя, и в общей сложности требовать 32-битной памяти, либо иметь явный бит знака, который означает что он также имеет 32-битное хранилище.

16 голосов
/ 02 декабря 2010

Ответ окончательно ДА. Прочитайте мой ОП и все комментарии, чтобы понять, почему именно, но вот короткая версия. Если вы сомневаетесь или сомневаетесь в этом, я советую вам прочитать всю ветку и все комментарии. В противном случае примите это как истину:

  1. Стандарт C ++ включает части стандарта C, включая определения для LONG_MIN и LONG_MAX
  2. LONG_MIN определяется как не более -2147483647
  3. LONG_MAX определяется как не менее +2147483647
  4. В C ++ интегральные типы хранятся в двоичном виде в базовом представлении
  5. Чтобы представить -2147483647 и +2147483647 в двоичном формате, вам нужно 32 бита.
  6. Длина C ++ гарантированно может представлять минимальный диапазон от LONG_MIN до LONG_MAX

Следовательно, long должно быть не менее 32 бит 1 .

EDIT:

LONG_MIN и LONG_MAX имеют значения с величинами, определяемыми стандартом C (ISO / IEC 9899: TC3) в разделе §5.2.4.2.1:

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

— minimum value for an object of type long int
LONG_MIN -2147483647 // -(2 ^ 31 - 1)
— maximum value for an object of type long int
LONG_MAX +2147483647 // 2 ^ 31 - 1

1 32 бита : это не означает, что sizeof (long) >= 4, поскольку байт не обязательно равен 8 битам. Согласно Стандарту, байт - это некое неопределенное (определяемое платформой) количество бит. Хотя большинство читателей сочтут это странным, есть реальное оборудование, на котором CHAR_BIT равно 16 или 32.

7 голосов
/ 02 декабря 2010

Но Альф и другие конкретно длина должна быть не менее 32 бит. Это что я пытаюсь установить. C ++ Стандарт явно, что число битов в байте не указаны. Может быть 4, 8, 16, 42 ... Так как же соединение сделано из возможности разместить номера LONG_MIN-LONG_MAX до 32 лет биты?

Вам нужно 32 бита в представлении значения, чтобы получить как минимум столько битовых шаблонов. А поскольку C ++ требует двоичного представления целых чисел (об этом явно говорится в стандарте, §3.9.1 / 7), Q.E.D.

7 голосов
/ 02 декабря 2010

Стандарт C ++ отмечает, что содержимое <climits> совпадает с заголовком C <limits.h> (18.2.2 в ISO C ++ 03 doc).

К сожалению, у меня нет копии стандарта C, существовавшего до C ++ 98 (т.е. C90), но в C99 (раздел 5.2.4.2.1), <limits.h> должен иметь вминимум это минимальные значения.Я не думаю, что это изменилось с C90, за исключением C99, добавив long long типов.

— minimum value for an object of type long int

LONG_MIN -2147483647 // −(2^31 − 1)

— maximum value for an object of type long int

LONG_MAX +2147483647 // 2^31 − 1

— maximum value for an object of type unsigned long int

ULONG_MAX 4294967295 // 2^32 − 1

— minimum value for an object of type long long int

LLONG_MIN -9223372036854775807 // −(2^63− 1)
6 голосов
/ 02 декабря 2010

Да, стандарт C ++ явно указывает, что число битов в байте не указано. Число битов в long тоже не указано.

Установка нижней границы для номера не является указанием it.

Стандарт C ++ гласит, в одном месте:

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

В сущности, в другом месте говорится о включении стандарта C:

CHAR_BITS >= 8; SHORT_BITS >= 16; INT_BITS >= 16; LONG_BITS >= 32

(за исключением того, что AFAIK, идентификаторы SHORT_BITS, INT_BITS и LONG_BITS не существуют, и что эти ограничения определяются требованиями для минимальных значений для типов.)

Это следует из того факта, что математически требуется определенное количество битов для кодирования всех значений в диапазоне (например, для длинных) LONG_MIN..LONG_MAX.

Наконец, шорты, целые и длинные должны состоять из целого числа символов; sizeof () всегда сообщает целое значение. Кроме того, перебор памяти char по char должен обращаться к каждому биту, что накладывает некоторые практические ограничения.

Эти требования не противоречат друг другу . Любые размеры, которые удовлетворяют требованиям, в порядке.

Давным-давно были машины с собственным размером слова 36 бит. Если бы вы перенесли на них компилятор C ++, вы могли бы по закону решить, что у вас должно быть 9 битов в символе, 18 в коротком и int и 36 в длинном. Вы также можете по закону принять 36 бит в каждом из этих типов, по той же причине, по которой вы можете иметь 32 бита в int в типичной 32-битной системе сегодня. Существуют реальные реализации, использующие 64-битные символы.

См. Также разделы 26.1-6 и 29.5 C ++ FAQ Lite .

...