Язык Си гарантирует только минимальный размер целочисленного типа, но на разных целевых системах он может быть и больше. Это значит, что программа, использующая тип, превышающий минимальные гарантированные диапазоны значений, может не работать в целевых системах, использующих меньший диапазон значений.
Чтобы облегчить кроссплатформенную переносимость, C99 определил набор целочисленных типов фиксированной ширины (в заголовочном файле stdint.h ), которые гарантированно будут иметь одинаковый размер в любой архитектуре.
Они определены следующим образом:
Название | Тип | Диапазон значений |
std::int8_t | 1 байт со знаком | от -128 до 127 |
std::uint8_t | 1 байт без знака | от 0 до 255 |
std::int16_t | 2 байта со знаком | от -32 768 до 32 767 |
std::uint16_t | 2 байта без знака | от 0 до 65 535 |
std::int32_t | 4 байт со знаком | от -2 147 483 648 до 2 147 483 647 |
std::uint32_t | 4 байта без знака | от 0 до 4 294 967 295 |
std::int64_t | 8 байт со знаком | от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 |
std::uint64_t | 8 байт без знака | от 0 до 18 446 744 073 709 551 615 |
Целочисленные типы фиксированной ширины имеют два недостатка:
Во-первых, они являются необязательными и существуют только в том случае, если есть базовые типы, соответствующие их ширине и следующие определенному двоичному представлению. Использование целочисленного типа фиксированной ширины делает ваш код менее портируемым, он может не компилироваться в других системах.
Во-вторых, если вы используете целочисленный тип фиксированной ширины, на некоторых архитектурах он может быть медленнее, чем более широкий тип. Если вам нужен целочисленный тип для хранения значений от -10 до 20, у вас может возникнуть соблазн использовать std::int8_t
. Но ваш процессор мог бы лучше обрабатывать 32-битные целые числа, поэтому вы просто потеряли скорость, сделав ограничение, в котором не было необходимости.
Чтобы устранить указанные выше недостатки язык определяет четыре альтернативных набора целочисленных типов.
Быстрый тип std::int_fast#_t обеспечивает самый быстрый целочисленный тип со знаком с шириной не менее # бит (где # = 8, 16, 32 или 64). Например std::int_fast32_t предоставит вам самый быстрый целочисленный тип со знаком, имеющий как минимум 32 бита.
Наименьший по размеру тип std::int_least#_t предоставляет наименьший по размеру целочисленный тип со знаком с шириной не менее # бит (где # = 8, 16, 32 или 64). Например: std::int_least32_t предоставит вам наименьший целочисленный тип со знаком, имеющий как минимум 32 бита.
Еще два типа являются соответствующими аналогами для типов без знака std::uint_fast#_t и std::uint_least#_t.
Из-за упущения в спецификации большинство компиляторов определяют и обрабатывают std::int8_t и std::uint8_t и соответствующие быстрые и наименьшие по размеру фиксированные типы идентично типам signed char и unsigned char соответственно. Следовательно std::cin и std::cout могут работать иначе, чем вы ожидаете. Ниже приведен пример программы, показывающей это:
#include<cstdint>
#include<iostream>
main( ) {
int8_t myint{65};
std::cout << myint;
return 0;
}
В большинстве систем эта программа будет печатать символ `A` (обрабатывая myint как символ). Однако в некоторых системах может быть напечатано 65, как и ожидалось. Для простоты лучше вообще избегать std::int8_t и std::uint8_t
Лучшие практики работы с целочисленными типами:
Следует использовать тип int всегда, когда максимальное значение переменной не превышает 16 бит. Это покроет подавляющее большинство случаев, с которыми вы, вероятно, столкнетесь.
Если вам нужна переменная гарантированно определенного размера, и вы хотите повысить производительность, используйте std::int_fast#_t.
Если вам нужна переменная, гарантированно имеющая определенный размер, и вы хотите отдать предпочтение экономии памяти над производительностью, используйте std::int_least#_t.
По возможности избегайте следующего:
- Беззнаковые типы, если у вас нет веской причины.
- 8-битные целочисленные типы фиксированной ширины.
- Любые специфичные для компилятора целочисленные типы фиксированной ширины
Тип size_t
Специальный тип данных size_t обычно используется для счетчиков циклов, индексации массивов, хранения размеров, адресной арифметики.
Размер данного типа совпадает с размером указателя. Если для этих целей использовать (unsigned int ) то на 64х разрядной платформе могут быть проблемы с корректной работой приложения, а также теоретическое снижение производительности при индексации.
Комментарии ()