Диапазон int – C++ | Типы данных

Вся правда о целочисленных типах в C / Habr

Для начала несколько вопросов:
  1. Тип char по умолчанию знаковый или нет? А int?
  2. Законно ли неявное приведение (signed char *) к (char *)? А то же для int?
  3. Сколько бит в unsigned char?
  4. Какое максимальное число гарантированно можно поместить в int? А минимальное?
  5. Тип long определённо больше, чем char, не так ли?

Разумеется, экспериментально искать ответы на эти вопросы с помощью вашего любимого компилятора в вашей любимой системе на вашем любимом компьютере1) — не лучшая идея. Мы говорим о стандарте языка (С99 и новее).

Если вы уверенно сможете правильно ответить на эти вопросы, тогда эта статья не для вас. В противном случае десять минут, потраченные на её чтение, будут весьма полезны.

Предположу, что вы ответили
  1. Знаковые оба.
  2. Законны оба.
  3. 8.
  4. 2147483647. -2147483648.
  5. Конечно, Кэп.


А правильные ответы такие
  1. char — не регламентируется, int — знаковый.
  2. Для int — законно, а для char — нет.
  3. Не менее 8.
  4. 32767. -32767
  5. Вообще говоря, нет.

Про 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_BIT2)) для данной платформы записано в заголовочном файле limits.h.

Размеры целочисленных типов в С

C переносимый, поэтому в нём базовые целочисленные типы (char, short, int и др.) не имеют строго установленного размера, а зависят от платформы. Однако эти типы не были бы переносимы, если бы
их размеры были совершенно произвольные: стандарт устанавливает минимальные диапазоны принимаемых значений для всех базовых целочисленные типов. А именно,
  • signed char: -127…127 (не -128…127; аналогично другие типы)
  • unsigned char: 0…255 (= 28−1)
  • signed short: -32767…32767
  • unsigned short: 0…65535 (= 216−1)
  • signed int: -32767…32767
  • unsigned int: 0…65535 (= 216−1)
  • signed long: -2147483647…2147483647
  • unsigned long: 0…4294967295 (= 232−1)
  • signed long long: -9223372036854775807…9223372036854775807
  • unsigned 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, но по причинам совместимости он называется так, как называется.

habr.com

Типы данных

Основные типы данных Турбо Паскаля имеют соответствующие эквиваленты в Турбо Си. Однако Си имеет как значительно большее разнообразие типов данных с широким выбором числовых диапазонов для значений целых и с плавающей точкой, так и спецификаторов signed и unsigned (со знаком и без знака). В Си по сравнению с Паскалем отсутствуют типы: диапазон, логический, процедурный (вместо него есть указатель на функцию), строковый, множество.

Кроме того, в Си в отличие от Паскаля, есть правила умолчания. Так, если забыли описать переменную, то по умолчанию она получит тип Signed int.

Классификация типов данных

Модификаторы типа:

Целые

(пределы их значений в Си хранятся в limits.h)

unsigned char (1 байт) 0 — 255

unsigned char (1 байт) 0 – 255

Замечания:

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

d=c-‘s’;

для представления русских символов требуется unsigned char (по умолчанию будет signed char)

signed char 1 байт (-128 .. +127)

Замечание: можно явно не указывать signed. Оно подразумевается по умолчанию

short (2 байта) -32768..32767 (всегда 2 байта)

int (2 байта) -32769..32767 (или 4 байта)

по умолчанию размер int совпадает с размером слова на данной ЭВМ (на 16-разр. ЭВМ — 16 бит, на 32-разр. ЭВМ — 32 бит = 4 байта)

unsigned int (2 байта) 0..65535. У констант суффикс U : 325U

long (4 байта) -2^31..2^31-1. У констант суффикс L: 75000L

unsigned long (4 байта) 0..(2^32-1). У констант суффикс UL: 125000UL

В ASNI C-99 long long – 8 байт.

Вещественные

(пределы их значений в Си хранятся в float.h)

Имя типа

размер

диапазон

float

4 байта

±3.4E+308

double

8 байт

±1.7E+308

long double

10 байт

unsigned long

8 байт

Логический

В Си нет логического типа данных: выражения, в которых требуются логические значения, интерпретируют значения «ноль», как false(ложь), а все другие (не равные нулю), как «true» (истина).

В Borland C++ есть тип BOOL со значениями false и true.

Диапазоны представления данных

Тип

Размер,

бит

Диапазон

unsigned char

8

0…255

char

8

128127

enum

16

32 76832 767

unsigned short

16

065535

short

16

3276832767

unsigned int

16

32

0…65535

04 294 967 295

int

16

32

32 768…32 767

2 147 483 648 …2 147 483 647

unsigned long

32

04 294 967 295

long

32

2 147 483 648 …2 147 483 647

float

32

3.4*10–383.4*10+38

double

64

1.7*10–3081.7*10+308

long double

80

1.7*1049321.7*10+4932

pointer

16

32

(указатели near, _cs, _ds, _es, _ss)

(указатели far, huge)

Объявление переменных

Основная форма объявления переменных имеет вид

type <список_переменных> ;

Здесь type должен быть одним из существующих в С типов переменных, а <список_переменных> может состоять из одной или нескольких переменных, разделенных запятыми. При объявлении переменных компилятор выделяет место в памяти компьютера, необходимое для размещения переменной данного типа. Примеры объявлений переменных:

int x, у, z;

float radius;

unsigned char ch;

long double integral;

studfile.net

Общаться с 64-битным long long в Visual C++ / Sandbox / Habr

Тип данных long long — это единственный целочисленный тип данных в Visual С++, который весит 8 байт и может использовать значения выше 2^31 — 1…..-2^31. Если у вас 64-битная система, то тип long тоже будет 8-байтовым. А в 32-разрядной системе приходится довольствоваться только им. Этот тип данных получил права только в последних версиях С++, например, в С++ 6.0 вы его найдёте, но работать с ним там одно удовольствие.

Несмотря на то, что у long long есть закреплённые права и обязанности. Использовать его всё равно следует по-особенному. Для начала следует учесть, что простое присваивание ему значений не прокатит. Если вы хотите присвоить значение переменной типа long long, то не забудьте приставить к числу две буквы LL (которые видимо символизируют, что число «longlong» 64-битное).

long long temp = 1100LL;

Далее: про соответствие типов. Думаю, когда человек первый раз «берёт в руки» этот тип данных ему становится интересно, а как он соотносится с типом int?

Отношения у long long c int очень интересные. Если вы хотите складывать два числа int, зная, что результат выйдет за диапазон int, то вы можете использовать long long. Сложите два int присвоите long long и все будут счастливы.

int a1 = 2000000000;
int a2 = 2000000000;
long long b = a1 + a2;

b равен 400000000. И здесь проблем возникнуть не должно.

С умножением int’ов дела гораздо интереснее. Если вы просто возьмёте две переменные типа int и перемножите их между собой, зная, что результат выйдет за пределы int, то ничего у вас не получится. Переменная типа long long будет просто равна нулю. В итоге, чтобы умножать в Visual C++ числа типа int и получить long long следует проделать сложения через цикл, т.е. если мы хотим умножить число а на число b, то всё будет выглядеть так.

long long temp = 0;
for (int i = 0; i < a; i++) {
temp += b;
}

И только тогда захочет быть произведением.

habr.com

Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *