Для начала несколько вопросов:
Разумеется, экспериментально искать ответы на эти вопросы с помощью вашего любимого компилятора в вашей любимой системе на вашем любимом компьютере1) — не лучшая идея. Мы говорим о стандарте языка (С99 и новее).
Если вы уверенно сможете правильно ответить на эти вопросы, тогда эта статья не для вас. В противном случае десять минут, потраченные на её чтение, будут весьма полезны.
Про
Все целочисленные типы кроме
С
Хотя формально это три разных типа, но фактически
Подробнее про
О размере
Тип
Стандарт С вынужден отказаться от допотопных архитектур и требует, чтобы байты были как минимум 8-битные. Конкретное значение (
C переносимый, поэтому в нём базовые целочисленные типы (
их размеры были совершенно произвольные: стандарт устанавливает минимальные диапазоны принимаемых значений для всех базовых целочисленные типов. А именно,
Стандарт требует, чтобы максимальное значение
Стандарт требует
Конкретные значения этих диапазонов для данной платформы указаны заголовочном файле
После того, как C99 добавил тип
least- и fast-типы фактически являются заменой рассмотренных выше типов
От типов вроде
1) Для удобства тройку архитектура+ОС+компилятор далее будем называть просто платформой.
2) Этот макрос правильнее было бы назвать
- Тип
char
по умолчанию знаковый или нет? Аint
? - Законно ли неявное приведение
(signed char *)
к(char *)
? А то же дляint
? - Сколько бит в
unsigned char
? - Какое максимальное число гарантированно можно поместить в
int
? А минимальное? - Тип
long
определённо больше, чемchar
, не так ли?
Разумеется, экспериментально искать ответы на эти вопросы с помощью вашего любимого компилятора в вашей любимой системе на вашем любимом компьютере1) — не лучшая идея. Мы говорим о стандарте языка (С99 и новее).
Если вы уверенно сможете правильно ответить на эти вопросы, тогда эта статья не для вас. В противном случае десять минут, потраченные на её чтение, будут весьма полезны.
Предположу, что вы ответили
- Знаковые оба.
- Законны оба.
- 8.
- 2147483647. -2147483648.
- Конечно, Кэп.
А правильные ответы такие
char
— не регламентируется,int
— знаковый.- Для
int
— законно, а дляchar
— нет. - Не менее 8.
- 32767. -32767
- Вообще говоря, нет.
Про signed
и unsigned
Все целочисленные типы кроме
char
, по умолчанию знаковые (signed).С
char
ситуация сложнее. Стандарт устанавливает три различных типа: char
, signed char
, unsigned char
. В частности, указатель типа (signed char *)
не может быть неявно приведён к типу (char *)
.Хотя формально это три разных типа, но фактически
char
эквивалентен либо signed char
, либо unsigned char
— на выбор компилятора (стандарт ничего конкретного не требует).Подробнее про
char
я написал в комментариях.О размере unsigned char
Тип
unsigned char
является абстракцией машинного байта. Важность этого типа проявляется в том, что С может адресовать память только с точностью до байта. На большинстве архитектур размер байта равен 8 бит, но бывают и исключения. Например, процессоры с 36-битной архитектурой как правило имеют 9-битный байт, а в некоторых DSP от Texas Instruments байты состоят из 16 или 32 бит. Древние архитектуры могут иметь короткие байты из 4, 5 или 7 бит.Стандарт С вынужден отказаться от допотопных архитектур и требует, чтобы байты были как минимум 8-битные. Конкретное значение (
CHAR_BIT
2)) для данной платформы записано в заголовочном файле limits.h
.Размеры целочисленных типов в С
C переносимый, поэтому в нём базовые целочисленные типы (
char
, short
, int
и др.) не имеют строго установленного размера, а зависят от платформы. Однако эти типы не были бы переносимы, если бы их размеры были совершенно произвольные: стандарт устанавливает минимальные диапазоны принимаемых значений для всех базовых целочисленные типов. А именно,
signed char:
-127...127 (не -128...127; аналогично другие типы)unsigned char
: 0...255 (= 28−1)signed short
: -32767...32767unsigned short
: 0...65535 (= 216−1)signed int
: -32767...32767unsigned int
: 0...65535 (= 216−1)signed long
: -2147483647...2147483647unsigned long
: 0...4294967295 (= 232−1)signed long long
: -9223372036854775807...9223372036854775807unsigned long long
: 0...18446744073709551615 (= 264−1)
Стандарт требует, чтобы максимальное значение
unsigned char
было 2CHAR_BIT−1 (см. предыдущий пункт).Стандарт требует
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
. Таким образом, вполне законны ситуации типа sizeof(char)=sizeof(long)=32
. Для некоторых DSP от Texas Instruments так и есть.Конкретные значения этих диапазонов для данной платформы указаны заголовочном файле
limits.h
.Новые типы в С99
После того, как C99 добавил тип
long long
, целочисленных типов и путаницы стало ещё больше. Чтобы навести порядок, стандарт ввёл заголовочный файл stdint.h
, где определяются типы вроде int16_t
(равно 16 бит), int_least16_t
(минимальный тип, способный вместить 16 бит), int_fast16_t
(по крайней мере 16 бит, работа с этим типом наиболее быстрая на данной платформе) и т. п.least- и fast-типы фактически являются заменой рассмотренных выше типов
int
, short
, long
и т. п. только вдобавок дают программисту возможность выбора между скоростью и размером.От типов вроде
int16_t
, со строгим указанием размера, страдает переносимость: скажем, на архитектуре с 9-битным байтом может просто не найтись 16-битного регистра. Поэтому стандарт тут явно говорит, что эти типы опциональны. Но учитывая, что какой бы код вы ни писали, чуть менее чем во всех случаях целевая архитектура фиксирована даже в худшем случае с точностью до семейства (скажем, x86 или AVR), внутри которого, размер байта не может вдруг поменяться, то переносимость фактически сохраняется. Более того, типы вроде int16_t
оказались даже более популярными, чем int_least16_t
и int_fast16_t
, а при низкоуровневом программировании (микроконтроллеры, драйверы устройств) и подавно, ибо там зачастую неопределённость размера переменной просто непозволительна.1) Для удобства тройку архитектура+ОС+компилятор далее будем называть просто платформой.
2) Этот макрос правильнее было бы назвать
UCHAR_BIT
, но по причинам совместимости он называется так, как называется.