Если бы я составлял викторину на тему ”размеры типов данных в 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
int16_t
int32_t
int64_t

Целочисленный знаковый тип размером 8, 16, 32 и 64 бита соответственно без бит-заполнителей и с использованием дополнительного кода для отрицательных значений (доступен только в том случае, если реализация напрямую поддерживает тип)

int_least8_t
int_least16_t
int_least32_t
int_least64_t

Наименьший целочисленный знаковый тип размером не менее 8, 16, 32 и 64 бит соответственно

intmax_t

Целочисленный знаковый тип максимального размера, поддерживаемого реализацией

uint8_t
uint16_t
uint32_t
uint64_t

Целочисленный тип со знаком размером 8, 16, 32 и 64 бит соответственно (доступен только если реализация напрямую поддерживает тип)

uint_least8_t
uint_least16_t
uint_least32_t
uint_least64_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».

Комментарии (12)