4.4 – Целочисленные типы данных со знаком
Целочисленное значение – это целочисленный тип, который может представлять положительные и отрицательные целые числа, включая 0 (например, -2, -1, 0, 1, 2). В C++ доступно 4 различных встроенных целочисленных типа:
Тип | Минимальный размер | Примечание |
---|---|---|
short | 16 бит | |
int | 16 бит | На современных архитектурах размер обычно составляет 32 бита |
long | 32 бита | |
long long | 64 бита |
Ключевое различие между различными целочисленными типами заключается в том, что они имеют разные размеры – бо́льшие целочисленные типы могут содержать больши́е числа.
Напоминание
C++ гарантирует только то, что целочисленные типы будут иметь определенный минимальный размер, а не то, что они будут иметь конкретный размер. Для получения информации о том, как определить размер каждого типа на вашем компьютере, смотрите урок «4.3 – Размеры объектов и оператор sizeof
».
Целочисленные значения со знаком
При написании отрицательных чисел в повседневной жизни мы используем знак минус. Например, -3 означает «отрицательное 3». Мы также обычно распознаем +3 как «положительное 3» (хотя общепринятое соглашение гласит, что мы обычно опускаем префиксы плюс). Этот атрибут, указывающий является ли число положительным, отрицательным или нулевым, называется знаком числа.
По умолчанию целочисленные значения со знаком, что означает, что знак числа сохраняется. Следовательно, целочисленное значение со знаком может содержать как положительные, так и отрицательные числа (и 0).
В этом уроке мы сосредоточимся на целочисленных значениях со знаком. Беззнаковые целочисленные значения (которые могут содержать только неотрицательные числа) мы обсудим в следующем уроке.
Определение целочисленных значений со знаком
Ниже показан предпочтительный способ определения четырех типов целочисленных значений со знаком:
short s;
int i;
long l;
long long ll;
Все целочисленные значения (кроме int
) могут иметь необязательный суффикс int:
short int si;
long int li;
long long int lli;
Но этот суффикс использовать не следует. Добавление суффикса int не только увеличивает количество набираемого текста, но и усложняет отличие этих типов от переменных типа int
. Это может привести к ошибкам, если случайно будет пропущен модификатор short
или long
.
Целочисленные типы также могут принимать необязательное ключевое слово signed
(т.е. со знаком), которое по соглашению обычно помещается перед именем типа:
signed short ss;
signed int si;
signed long sl;
signed long long sll;
Однако это ключевое слово так же не следует использовать, поскольку оно избыточно, так как по умолчанию целочисленные значения уже со знаком.
Лучшая практика
Используйте сокращенную запись типов, которая не используют суффикс int или префикс signed.
Диапазоны целочисленных значений со знаком
Как вы узнали в предыдущем разделе, переменная размером n бит может содержать 2n возможных значений. Но каких именно значений? Набор конкретных значений, которые тип данных может принимать, мы называем его диапазоном. Диапазон целочисленной переменной определяется двумя факторами: ее размером (в битах) и тем, со знаком она или нет.
По определению, 8-битное целочисленное значение со знаком имеет диапазон от -128 до 127. Это означает, что целочисленное значение со знаком может безопасно хранить любое целое число от -128 до 127 (включительно).
В качестве отступления...
Время для математики: 8-битное целочисленное значение содержит 8 бит. 28 равно 256, поэтому 8-битное целочисленное значение может содержать 256 возможных значений. Возможны 256 значений от -128 до 127 включительно.
Ниже показана таблица, содержащая диапазон целочисленных значений со знаком разных размеров:
Размер / Тип | Диапазон |
---|---|
8 бит со знаком | от -128 до 127 |
16 бит со знаком | от -32 768 до 32 767 |
32 бита со знаком | от -2 147 483 648 до 2 147 483 647 |
64 бита со знаком | от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 |
Для математических расчетов: переменная размером n бит и со знаком имеет диапазон от -(2n-1) до 2n-1-1.
Для тех, кто не склонен к математике… воспользуйтесь таблицей. :)
Переполнение целочисленных значений
Что произойдет, если мы попытаемся присвоить значение 280 8-битному целочисленному значению со знаком? Это число выходит за пределы диапазона, который может содержать 8-битовое целочисленное значение со знаком. Для числа 280 требуется 9 бит (плюс 1 бит для знака), но в 8-битном целочисленном значении со знаком у нас есть только 7 бит (плюс 1 бит для знака).
Переполнение целочисленных значений (часто для краткости называемое просто переполнением) происходит, когда мы пытаемся сохранить значение, выходящее за пределы диапазона типа. По сути, число, которое мы пытаемся сохранить, требует для представления большее количества бит, чем доступно объекту. В таком случае данные теряются, потому что объекту для хранения всего не хватает памяти.
В случае целочисленных значений со знаком, какие биты теряются, точно не определено, таким образом, переполнение целочисленного значения со знаком приводит к неопределенному поведению.
Предупреждение
Переполнение целочисленного значения со знаком приведет к неопределенному поведению.
Как правило, переполнение приводит к потере информации, что почти никогда не бывает желательно. Если есть подозрение, что объекту может потребоваться сохранить значение, выходящее за пределы его диапазона, используйте тип с большим диапазоном!
Деление целочисленных значений
При делении двух целочисленных значений, когда частное представляет собой целое число, C++ работает так, как вы ожидаете:
#include <iostream>
int main()
{
std::cout << 20 / 4;
return 0;
}
Это дает ожидаемый результат:
5
Но давайте посмотрим, что происходит, когда целочисленное деление приводит к дробному результату:
#include <iostream>
int main()
{
std::cout << 8 / 5;
return 0;
}
Это дает, возможно, неожиданный результат:
1
При делении двух целочисленных значений (так называемое целочисленное деление) C++ всегда дает целочисленный результат. Поскольку целые числа не могут содержать дробные значения, любая дробная часть просто отбрасывается (не округляется!).
Если присмотреться к приведенному выше примеру, 8/5 дает значение 1,6. Дробная часть (0,6) отбрасывается, и в результате остается 1.
Аналогично, -8/5 дает значение -1.
Предупреждение
Будьте осторожны при использовании целочисленного деления, так как вы потеряете дробную часть частного. Однако, если это то, что вам нужно, то целочисленное деление использовать можно, так как результаты предсказуемы.
Если вам необходимы дробные результаты, мы покажем способ их получить в уроке «5.2 – Арифметические операторы».