Menu

Типы данных в C++: int, double, char, bool и другие

Практический обзор фундаментальных типов данных C++ - целых чисел, чисел с плавающей точкой, char и bool - а также размеров, signed и unsigned, литералов и суффиксов, переполнения и того, как выбрать правильный тип.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Почему типы важны в C++

На странице о переменных вы объявляли значения с явным типом, например int age = 30;. Этот тип - не просто ярлык: он сообщает компилятору, сколько байтов зарезервировать, как интерпретировать эти байты и какие операции допустимы. Ошибитесь с типом - и вы можете незаметно потерять точность, получить переполнение или вызвать неопределённое поведение.

C++ группирует встроенные типы в несколько семейств: целые числа, числа с плавающей точкой, символьный тип и логический. Рассмотрим каждый, а затем правила, на которых люди спотыкаются.

Фундаментальные типы

Вот по одному примеру каждого основного типа в одной программе. Обратите внимание на суффиксы литералов (L, f, u) и одинарные кавычки у char:

bool по умолчанию печатается как 1 или 0, а не true/false. char использует одинарные кавычки - 'A' это один символ, тогда как "A" (двойные кавычки) это строковый литерал, совершенно другой тип. Эти две ошибки крайне распространены на старте.

Размеры не фиксированы

Это самый большой сюрприз для тех, кто пришёл из языков вроде Java. Стандарт C++ гарантирует только минимальные размеры и относительный порядок (shortintlonglong long). Фактический размер зависит от вашего компилятора и платформы. Всегда проверяйте через sizeof:

В типичной 64-битной сборке для Linux вы увидите int = 4, long = 8. Однако в 64-битной Windows long занимает всего 4 байта. Именно этот разрыв в переносимости и есть причина, по которой не стоит писать код, предполагающий, что long 64-битный.

Когда нужна точная разрядность, обратитесь к целочисленным типам фиксированной ширины из <cstdint>:

Используйте int32_t/int64_t для форматов файлов, сетевых протоколов или всего, что должно вести себя одинаково на разных машинах. Обратите внимание на приведение (int)a - вывод 8-битного типа в поток печатает его как символ, а не как число, поэтому сначала выполните приведение.

Signed и unsigned

Каждый целочисленный тип бывает двух разновидностей. Тип signed может хранить отрицательные значения; тип unsigned не может, обменивая отрицательный диапазон на больший положительный максимум. Обычный int по умолчанию signed.

Вычитание из беззнакового 0 оборачивается в огромное положительное число вместо того, чтобы стать отрицательным. На этом люди попадаются постоянно - особенно с size_t (беззнаковый тип), возвращаемым .size():

vector<int> v = {1, 2, 3};
// ОПАСНО: v.size() беззнаковый. Если v пуст, v.size() - 1 оборачивается
// в гигантское число, и цикл выполняется почти бесконечно.
for (size_t i = 0; i <= v.size() - 1; i++) { /* ... */ }

Предпочитайте i < v.size() (никогда <= size() - 1) или обойдите проблему целиком с помощью цикла for по диапазону.

Переполнение целых чисел - это неопределённое поведение

В отличие от оборачивания беззнаковых (которое чётко определено), переполнение знакового целого числа в C++ является неопределённым поведением. Компилятору разрешено делать что угодно - вернуть мусор, выкинуть проверку при оптимизации или аварийно завершиться:

Решение такое же, как и ловушка переполнения в любом языке: выполняйте арифметику в более широком типе. Приведите один операнд к long long перед +, чтобы сложение происходило в 64 битах. Приводить результат после уже поздно - переполнение уже случилось.

Выбор правильного типа

Для большей части кода значения по умолчанию подходят: int для целых чисел, double для дробных. Обращайтесь к чему-то ещё только тогда, когда на это есть причина.

ТипТипичный размерИспользовать, когда
int32 битаПо умолчанию для целых чисел
long long64 битаЗначения свыше ~2 млрд: метки времени, большие счётчики
double64 битаПо умолчанию для дробных - хорошая точность
float32 битаМассивы с ограниченной памятью, где точностью можно пожертвовать
bool1 байтФлаг true/false
int32_t / int64_tточныйКроссплатформенные форматы, протоколы, работа с битами

Пара подводных камней, о которых стоит помнить. У float всего около 7 значащих десятичных цифр, поэтому 0.1f + 0.2f не равно в точности 0.3 - предпочитайте double, если только вам действительно не нужно экономить память. А char может быть signed или unsigned в зависимости от платформы, поэтому, если вы делаете арифметику над сырыми байтами, явно указывайте signed char или unsigned char.

Далее: Ключевое слово auto

Выписывать тип каждый раз утомительно, а иногда тип длинный или его трудно назвать. C++ позволяет компилятору вывести его за вас с помощью ключевого слова auto - auto x = 42; делает x типом int, а auto it = v.begin(); избавляет от набора многословного типа итератора. Следующая страница рассказывает, когда auto делает код яснее, а когда скрывает слишком многое.

Часто задаваемые вопросы

Какие основные типы данных есть в C++?

Фундаментальные типы - это целые числа (short, int, long, long long), числа с плавающей точкой (float, double, long double), символьный тип char и логический тип bool. Каждый целочисленный тип также может быть signed или unsigned. Всё остальное - std::string, массивы, ваши собственные классы - строится поверх них.

В чём разница между int и long в C++?

Оба хранят целые числа, но гарантируется, что long будет не уже, чем int (часто 64 бита на 64-битных платформах, но всего 32 бита в Windows). Стандарт фиксирует только минимальные размеры, поэтому для гарантированной разрядности используйте типы фиксированной ширины из <cstdint>, такие как int32_t и int64_t.

Какого размера int в C++?

Стандарт гарантирует только, что int имеет не менее 16 бит, но практически на любом современном настольном компьютере и сервере это 32 бита. Поскольку размеры зависят от платформы, никогда не делайте предположений - выведите sizeof(int), чтобы проверить, или используйте типы из <cstdint>, такие как int32_t, когда нужна точная разрядность.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ