Если бы я составлял викторину на тему ”размеры типов данных в C++”, большинство разработчиков C++ не справились бы с ней (я уверен, что я бы тоже ее завалил), потому что размеры в C++ немного сложнее, чем кажутся.
Размер каждого базового типа данных не является фиксированным, они всегда зависят от реализации.
Тем не менее, стандарт накладывает некоторые ограничения на эти размеры. Эти ограничения по сути выливаются в два следующих пункта:
Соразмерность
sizeof
типов.Минимальное количество битов типа данных.
Что же такое sizeof()?
Одно из наиболее распространенных (и безобидных) заблуждений о размерах типов данных — это то, что байт содержит 8 бит.
Стоит отметить, что на практике в большинстве случаев это верное утверждение, но с технической точки зрения ошибочно так считать.
На практике байт определяется размером char
. char
должен содержать не менее 8 бит, но возможно и большее значение. sizeof(N)
возвращает количество байт типа N, а каждый размер типа выражается через длину char
. Таким образом, 4-байтовый int
является как минимум 32-битным, но большего сказать о нем вы не можете (если char
32-битный, int
может быть 128-битным).
Фактический размер байта прописан в CHAR_BIT
Виды размеров в C++
Ниже перечислены все определения и ограничения размеров основных типов в C++:
1 ≡ sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long)
1 ≤ sizeof(bool) ≤ sizeof(long)
sizeof(char) ≤ sizeof(wchar_t) ≤ sizeof(long)
sizeof(float) ≤ sizeof(double) ≤ sizeof(long double)
sizeof(N) ≡ sizeof(unsigned N) ≡ sizeof(signed N)
Char состоит как минимум из 8 бит.
Short состоит как минимум из 16 бит.
Long состоит как минимум из 32 бит.
… и на этом все.
Интересный факт: согласно этому определению технически возможно, чтобы все фундаментальные типы имели по 32 бита.
Парочка мудрых мыслей
Поскольку размеры фундаментальных типов полностью зависят от архитектуры, иногда писать согласованный код становится сложно.
#include
limits
стандартной библиотеки содержит верхние и нижние пределы каждого фундаментального типа, и позволяет узнать, знаковый (signed/unsigned) данный тип или нет.
Пример:
#include <limits>
#include <iostream>
int main()
{
std::cout << "largest double == " << std::numeric_limits<double>::max() << std::endl;
std::cout << "char is signed == " << std::numeric_limits<char>::is_signed << std::endl;
}
Подробнее об этом на std::numeric_limits - cppreference.com.
Напоминание: переполнение целого числа со знаком — неопределенное переопределение. Использование ограничений поможет вам предотвратить это.
#include
Порой может возникнуть желание работать только с типами фиксированного размера (имеются в виду биты) и не полагаться на особенности реализации. Например, если вы реализуете сериализацию, работаете с очень ограниченным количеством памяти или разрабатываете кроссплатформенное программное обеспечение, вы можете сразу указать размер в битах используемого вами типа.
Вы можете сделать это с помощью библиотеки cstdint
, которая содержит типы фиксированного размера.
Рассмотрим некоторые из них:
int8_t |
Целочисленный знаковый тип размером 8, 16, 32 и 64 бита соответственно без бит-заполнителей и с использованием дополнительного кода для отрицательных значений (доступен только в том случае, если реализация напрямую поддерживает тип) |
int_least8_t |
Наименьший целочисленный знаковый тип размером не менее 8, 16, 32 и 64 бит соответственно |
intmax_t |
Целочисленный знаковый тип максимального размера, поддерживаемого реализацией |
uint8_t |
Целочисленный тип со знаком размером 8, 16, 32 и 64 бит соответственно (доступен только если реализация напрямую поддерживает тип) |
uint_least8_t |
Самый маленький целочисленный тип без знака размером не менее 8, 16, 32 и 64 бит соответственно |
uintmax_t |
Целочисленный тип без знака максимального размера |
Здесь вы можете найти больше информации о целочисленных типах с фиксированным размером (начиная с C++11) -cppreference.com.
Заключение
Больше информации о размерах типов вы найдете в разделе §6.2.8 The C++ Langage (Bjarne Stroustrup). Более глубоко познакомиться с типами и их определениями вы можете в §6 разделе этой книги.
Также у вас есть возможность почитать онлайн-документацию на сайте Fundamental types – cppreference.com
Материал подготовлен в рамках курса «C++ Developer. Basic».