Урок 31. Целочисленный тип данных. Integer

   ⁄ 

 Обновлено 17 Апр 2017

  ⁄   

⁄  4

Целочисленный тип (integer) – это тип, переменные которого могут содержать только целые числа, без дроби (например: -2, -1, 0, 1, 2). В C++ есть пять основных целочисленных типов, доступных для использования:

Категория Тип Минимальный размер Примечание
character char 1 байт
integer short 2 байта
int 2 байта В основном 4 байта на современных архитектурах
long 4 байта
long long 8 байтов тип C99/C++11

Тип char — особый случай, он относится как целочисленному, так и к символьному типам данных. Мы поговорим об особенностях char в отдельном уроке.

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

Определение целочисленных переменных

Пример:

В то время как полные названия short intlong int и long long int могут использоваться, их сокращенные версии (без int) более предпочтительны. К тому же постоянное добавление int затрудняет чтение кода, его легко можно спутать с переменной.

Поскольку размеры char, short, int и long могут варьироваться в зависимости от компилятора и/или архитектуры компьютера, то более рассудительным обращаться к ним будет по их размеру, а не по названию. Мы часто ссылаемся на типы данных по количеству битов, которые им выделяются (например, «32-битный integer» вместо «long»).

Диапазоны и знаки целочисленных типов

Как вы уже знаете с предыдущего урока, переменная с n-ным количеством битов может хранить 2возможных значений. Но какие конкретно? Те, которые находятся в диапазоне. Диапазон – это значения от и до, которые тип данных может хранить. Диапазон целочисленной переменной определяется двумя факторами: её размером (в битах) и её знаком, который может быть “signed” или “unsigned”.

signed (со знаком) означает, что переменная может содержать как положительные (плюсовые), так и отрицательные (минусовые) числа. Чтобы объявить переменную как signed, используйте ключевое слово signed:

По умолчанию, его пишут перед типом данных.

1-байтовая целочисленная переменная со знаком (signed) имеет диапазон от -128 до 127. Любое значение от -128 до 127 (включительно) может храниться в ней безопасно.

Иногда, мы заранее знаем, что не будем использовать отрицательные числа. Это очень часто встречается при использовании переменных для хранения количества или размера чего-либо (например, ваш рост – он ведь не может быть отрицательным). Целочисленный тип unsigned (без знака) может содержать только положительные значения. Чтобы объявить переменную как unsigned, используйте ключевое слово unsigned:

1-байтовая целочисленная переменная без знака имеет диапазон от 0 до 255.

Обратите внимание, что объявление переменной как unsigned означает, что она не сможет содержать отрицательные числа, только положительные.

Теперь, когда вы поняли разницу между signed и unsigned, давайте рассмотрим диапазоны типов данных с разным количеством байтов:

Размер/Тип Диапазон
1 байт signed от -128 до 127
1 байт unsigned от 0 до 255
2 байта signed от -32 768 до 32 767
2 байта unsigned от 0 до 65 535
4 байта signed от -2 147 483 648 до 2 147 483 647
4 байта unsigned от 0 до 4 294 967 295
8 байтов signed от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
8 байтов unsigned от 0 до 18 446 744 073 709 551 615

Для математиков: переменная signed с n-ным количеством битов имеет диапазон от -(2n-1) до 2n-1-1. Переменная unsigned с n-ным количеством битов имеет диапазон от 0 до (2n)-1. Для не математиков: используем таблицу 🙂

Начинающие программисты иногда путаются между signed и unsigned переменными. Но есть простой способ их запомнить. Чтобы отличить отрицательное число от положительного, мы, обычно, используем отрицательный знак (минус). Если знака нет, то мы предполагаем, что число является положительным. Следовательно, целочисленный тип со знаком (signed) означает, что знак может присутствовать, а, значит, числа могут быть как положительными, так и отрицательными. Целочисленный тип без знака (unsigned) исключает наличие минуса, поэтому числа могут быть только положительными.

Что стоит по умолчанию: signed или unsigned?

Так что же произойдет, если мы объявим переменную без указания signed или unsigned?

Категория Тип По умолчанию Примечание
character char signed или unsigned В основном signed
integer short signed
int signed
long signed
long long signed

Все целочисленные типы, кроме char, являются signed по умолчанию. Char же может быть как со знаком, так и без него (но, обычно, signed).

Как правило, ключевое слово signed не пишется (оно и так установлено по умолчанию), за исключением типа char (здесь лучше самому уточнить).

Программисты, как правило, избегают использование целочисленных типов unsigned (без знака), если нет особой необходимости в них, так как переменные unsigned более склонны к неожиданному поведению и ошибкам, нежели переменные signed.

Правило: Используйте целочисленные переменные signed, вместо unsigned.

Переполнение

Что произойдет, если мы попытаемся использовать значение, которое выходит за рамки диапазона определенного типа данных? Ответ: переполнение. Переполнение (overflow) означает потерю битов, так как переменной не было выделено достаточно памяти для их хранения.

В уроке 28 об адресах и инициализации переменных, мы упоминали, что данные хранятся в бинарном (двоичном) формате и каждый бит может иметь только 2 возможных значений (0 или 1). Вот так выглядят числа от 0 до 15 в обеих системах:

Десятичная система Двоичная система
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111

Как вы можете наблюдать, чем число больше, тем больше требуется битов. Поскольку наши переменные имеют фиксированный размер, то на них накладываются ограничения на количество данных, которые они могут хранить.

Примеры overflow

Рассмотрим переменную unsigned, которая состоит из 4 битов. Любое из двоичных чисел, перечисленных в таблице выше, поместится внутри этой переменной.

Но что произойдет, если мы попытаемся присвоить значение для нашей переменной, которое занимает больше 4 битов? Переполнение: наша переменная будет хранить только 4 наименее значимых (те, что справа) битов, все остальные потеряются.

Например, если мы попытаемся использовать число 21 в нашей 4-битной переменной:

Десятичная система Двоичная система
21 10101

Как вы видите, число 21 занимает 5 битов (10101). 4 крайние правые биты (0101) перейдут в переменную, а крайний левый бит (1) просто потеряется. Тогда наша переменная станет 0101, что равно 101 (нуль спереди не считается), а это уже число 5, а не 21.

Примечание: сейчас вы не должны знать, как переводить числа из десятичной системы в бинарную и наоборот. Для этого будет специальный урок в будущем.

Теперь в коде (тип short занимает 16 битов):

Как вы думаете, каков будет результат?

x was: 65535
x is now: 0

Что случилось? Мы переполнили переменную, пытаясь использовать число, которое было слишком большим (65536).

Для тех, кто хочет знать больше. Вот что на самом деле произошло за кулисами. Число 65 535 в двоичной системе выглядит вот так — 1111 1111 1111 1111. 65 535 – это наибольшее число, которое может хранить 2-байтовая (16 бит) целочисленная переменная без знака, так как это число использует все 16 битов. Когда мы добавляем 1, то результатом стает 65 536. Тем не менее, число 65 536 представлено в двоичной системе, как 1 0000 0000 0000 0000, и занимает 17 бит! Следовательно, самый главный бит (которым является 1) теряется, а все 16 битов, что справа, остаются. Следующая комбинация 0000 0000 0000 0000 соответствует числу 0, что и есть нашим результатом.

Аналогичным образом, мы получим переполнение, проделав обратное и с наименьшим числом из нашего диапазона.

x was: 0
x is now: 65535

Overflow приводит к потере информации, а это никогда не желательно. Если есть хоть малейшее подозрение или предположение, что значением переменной может быть число, которое выходит за пределы диапазона её типа – используйте тип данных побольше!

Правило: Не допускайте переполнение и не полагайтесь на его результаты в вашей программе.

Деление целочисленных переменных

При делении двух целых чисел, где результатом должно выйти другое целое число, C++ работает, как и следует ожидать:

Результат:

5

Но давайте посмотрим, что произойдет, если результатом деления двух целых чисел, должно выйти дробное число:

Результат:

1

В C++, при делении целых чисел результатом всегда будет другое целое число. А такие числа не могут иметь дробь (она просто отбрасывается, не округляется!).

Рассмотрим детальнее пример выше: 8 / 5, результатом должно выйти значение 1.6. Но как вы уже знаете, при делении целых чисел, результатом будет целое число. Таким образом, дробная часть (0.6) отбрасывается и остается 1.

Правило: Будьте осторожны при делении целых чисел, так как любая дробь в результате будет отбрасываться.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (26 оценок, среднее: 4,73 из 5)
Загрузка...
Поделиться в:
Подписаться на обновления:

Комментариев: 4

  1. Виталий:

    >>»Правило: Используйте целочисленные переменные signed, вместо unsigned.»

    Офигенное правило.
    unsigned изобрели просто так, чтоб им не пользоваться…

    1. Old G.B.:

      Претензии к автору предъявлять нельзя, он только лишь переводит.

      1. Li4ik:

        Это нормально, я ведь учусь вместе с вами. Отвечая на вопросы и претензии — лучше начинаешь понимать суть изучаемого сам 🙂

    2. Li4ik:

      Unsigned полезен лишь в конкретных случаях, когда вы знаете, что его использование не приведет к проблемам и сбою в программе, когда вы можете это гарантировать. Для более широкого использования (повседневного) рекомендуется тип signed, так как он менее подвержен ошибкам и более надежный. Всё просто —
      можете прислушивать, можете нет — ваше право.

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

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