Гарантируется ли `long` как минимум 32 бита?

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

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

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

  1. Существует четыре типа целых чисел со знаком: "знаковый символ", "короткое целое", "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.

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


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

  • ISO / IEC 2382 (все части), Информационные технологии. Словарь
  • ISO/IEC 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 ответов

Решение

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

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

Поэтому long должно быть не менее 32 бит1.

РЕДАКТИРОВАТЬ:

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.

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-битной памяти также.

Стандарт 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)

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

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

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

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

Стандарт 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.

Другие вопросы по тегам