Гарантируется ли `long` как минимум 32 бита?
Изучая стандарт C++, я всегда понимал, что размеры целочисленных фундаментальных типов в C++ были следующими:
sizeof(char) <= sizeof(short int) <= sizeof(int) <= sizeof(long int)
Я вывел это из 3.9.1/2:
- Существует четыре типа целых чисел со знаком: "знаковый символ", "короткое целое", "int" и "длинное целое". В этом списке каждый тип обеспечивает как минимум столько же памяти, сколько предшествует ему в списке. Простые целые имеют естественный размер, предложенный архитектурой среды исполнения
Далее размер char
описывается 3.9.1 / как:
- [...] достаточно большой, чтобы хранить любой элемент базового набора символов реализации.
1.7 / 1 определяет это в более конкретных терминах:
- Фундаментальным хранилищем в модели памяти C++ является байт. Байт, по крайней мере, достаточно большой, чтобы содержать любой элемент базового набора символов выполнения, и состоит из непрерывной последовательности битов, число которых определяется реализацией.
Это приводит меня к следующему выводу:
1 == sizeof(char) <= sizeof(short int) <= sizeof(int) <= sizeof(long int)
где sizeof
говорит нам, сколько байтов тип. Кроме того, это определяется реализацией, сколько битов в байте. Большинство из нас, вероятно, привыкли иметь дело с 8-битными байтами, но Стандарт говорит, что есть n
биты в байте.
В этом посте Альф П. Штейнбах говорит:
long гарантируется (как минимум) 32 бита.
Это противоречит всему, что, как я понимаю, соответствует размеру основных типов в C++ в соответствии со Стандартом. Обычно я просто игнорировал бы это утверждение, поскольку новичок ошибался, но, поскольку это был Альф, я решил, что его стоит продолжить.
Итак, что вы говорите? Гарантируется ли стандарт длиной не менее 32 бит? Если это так, пожалуйста, уточните, как предоставляется эта гарантия. Я просто не вижу этого.
Стандарт C++ конкретно говорит, что для того, чтобы знать C++, вы должны знать C (1.2 / 1) 1
Стандарт 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 ответов
Ответ окончательно ДА. Прочитайте мой ОП и все комментарии, чтобы понять, почему именно, но вот короткая версия. Если вы сомневаетесь или сомневаетесь в этом, я призываю вас прочитать всю ветку и все комментарии. В противном случае примите это как истину:
- Стандарт C++ включает в себя части стандарта C, включая определения для
LONG_MIN
а такжеLONG_MAX
LONG_MIN
определяется как не более чем-2147483647
LONG_MAX
определяется как не менее+2147483647
- В C++ интегральные типы хранятся в двоичном виде в базовом представлении
- Для того, чтобы представлять
-2147483647
а также+2147483647
в двоичном формате вам нужно 32 бита. - 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.