гарантия размера для целочисленных / арифметических типов в C и C ++ - PullRequest
9 голосов
/ 04 ноября 2010

Я знаю, что стандарт C ++ явно гарантирует размер только char, signed char и unsigned char.Также это дает гарантии того, что, скажем, short по крайней мере столь же велико, как char, int, равно short и т. Д. Но нет явных гарантий относительно абсолютной величины, скажем, sizeof(int).Это была информация в моей голове, и я жил с ней счастливо.Некоторое время назад, однако, я наткнулся на комментарий в SO (не могу его найти), что в C long гарантированно будет по крайней мере 4 байта, и это требование «унаследовано» от C ++.Это тот случай?Если да, то какие еще неявные гарантии мы имеем для размеров арифметических типов в C ++?Обратите внимание, что в этом вопросе меня совершенно не интересуют практические гарантии для разных платформ, только теоретические .

Ответы [ 7 ]

13 голосов
/ 04 ноября 2010

18.2.2 гарантирует, что <climits> имеет то же содержимое, что и заголовок библиотеки C <limits.h>.

Стандарт ISO C90 довольно сложен в использовании, и это позор, если учесть, что C ++ полагается на него, но раздел «Числовые пределы» (нумеруемый в случайном черновике 2.2.4.2, я однажды выследил и улег около) дает минимальные значения для констант INT_MAX и т. д. в <limits.h>. Например, ULONG_MAX должно быть не менее 4294967295, из чего мы выводим, что ширина long составляет не менее 32 бит.

Есть аналогичные ограничения в стандарте C99, но, конечно, это не те ограничения, на которые ссылается C ++ 03.

Это не гарантирует, что long равно как минимум 4 байта, поскольку в C и C ++ "byte" в основном определяется как "char", и не гарантируется, что CHAR_BIT 8 в C или C ++. CHAR_BIT == 8 гарантируется как POSIX, так и Windows.

12 голосов
/ 04 ноября 2010

Не знаю о C ++.В C у вас есть


                                  Annex E
                              (informative)


                          Implementation limits

       [#1]  The contents of the header  are given below,
       in alphabetical order.  The minimum magnitudes  shown  shall
       be  replaced  by  implementation-defined magnitudes with the
       same sign.  The values shall  all  be  constant  expressions
       suitable  for  use  in  #if  preprocessing  directives.  The
       components are described further in 5.2.4.2.1.

               #define CHAR_BIT                         8
               #define CHAR_MAX    UCHAR_MAX or SCHAR_MAX
               #define CHAR_MIN            0 or SCHAR_MIN
               #define INT_MAX                     +32767
               #define INT_MIN                     -32767
               #define LONG_MAX               +2147483647
               #define LONG_MIN               -2147483647
               #define LLONG_MAX     +9223372036854775807
               #define LLONG_MIN     -9223372036854775807
               #define MB_LEN_MAX                       1
               #define SCHAR_MAX                     +127
               #define SCHAR_MIN                     -127
               #define SHRT_MAX                    +32767
               #define SHRT_MIN                    -32767
               #define UCHAR_MAX                      255
               #define USHRT_MAX                    65535
               #define UINT_MAX                     65535
               #define ULONG_MAX               4294967295
               #define ULLONG_MAX    18446744073709551615

Итак char <= <code>short <= <code>int <= <code>long <= <code>long long

и

CHAR_BIT * sizeof (char)> = 8
CHAR_BIT * sizeof (short)> = 16
CHAR_BIT * размер (int)> = 16
CHAR_BIT * sizeof (long)> = 32
CHAR_BIT* sizeof (long long)> = 64

3 голосов
/ 04 ноября 2010

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

знаковый символ -127 ... +127 гарантирован, но большинство машин с двумя дополнениями имеют -128 ... + 127

Аналогично для больших типов.

3 голосов
/ 04 ноября 2010

Да, размеры типов C ++ унаследованы от C89.

Я не могу найти спецификацию прямо сейчас. Но это в Библии .

2 голосов
/ 04 ноября 2010

В том, что вы читаете, есть несколько неточностей. Эти неточности либо присутствовали в источнике, либо, возможно, вы все запомнили неправильно.

Во-первых, педантичное замечание об одном специфическом различии между C и C ++. Язык C не дает никаких гарантий относительно относительных размеров целочисленных типов (в байтах). Язык C только дает гарантии об их относительных диапазонах . Это правда, что диапазон int всегда по крайней мере такой же, как диапазон short и так далее. Тем не менее, согласно стандарту C формально разрешено иметь sizeof(short) > sizeof(int). В таком случае дополнительные биты в short будут служить дополнительными битами , не используемыми для представления значения. Очевидно, что это то, что просто разрешено юридическим языком в стандарте, а не то, с чем кто-либо может столкнуться на практике.

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

Во-вторых, стандарт языка C гарантирует минимальный диапазон для каждого целочисленного типа (эти гарантии присутствуют как в C, так и в C ++). Зная минимальный диапазон для данного типа, вы всегда можете сказать, сколько значений битов этого типа требуется иметь (как минимальное количество битов). Например, верно, что тип long должен иметь как минимум 32 формирующих значение бита, чтобы удовлетворять требованиям диапазона. Если вы хотите пересчитать это в байт , это будет зависеть от того, что вы понимаете под термином byte . Если вы говорите конкретно о 8-битных байтах, то тип long всегда будет состоять как минимум из четырех 8-битных байтов. Однако это не означает, что sizeof(long) всегда равно как минимум 4, поскольку в терминологии C / C ++ термин byte относится к char объектам. char объекты не ограничены 8 битами. В некоторых реализациях вполне возможно иметь 32-битный тип char, что означает, что sizeof(long) в байтах C / C ++ может по закону быть, например, 1.

1 голос
/ 04 ноября 2010

Только будьте осторожны с тем фактом, что некоторые машины имеют символы, которые больше 8 бит.Например, IIRC на TI C5x, long - 32 бита, но sizeof (long) == 2, потому что все символы, шорты и целые числа - 16 бит с sizeof (char) == 1.

1 голос
/ 04 ноября 2010

Стандарт C прямо не говорит, что long должен быть не менее 4 байтов, но они определяют минимальный диапазон для различных целочисленных типов, что подразумевает минимальный размер.

Например,минимальный диапазон unsigned long составляет от 0 до 4 294 967 295.Вам нужно как минимум 32 бита для представления каждого числа в этом диапазоне.Так что да, стандартная гарантия (косвенно), что long не менее 32 бит.

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

...