Получить самый большой целочисленный тип со знаком в C++
Допустим, я должен принять размер в качестве аргумента интерфейса, который имеет дело с массивами. Для бывших
void doSomethingRelatedToArrays(const size_t length)
Здесь я использовал size_t, имея в виду следующее:
- длина всегда должна быть положительной
- size_t всегда typedef-ed для самого большого целого типа без знака в системе. std::size_t может хранить максимальный размер теоретически возможного объекта любого типа.
Однако я не должен использовать типы без знака в моих интерфейсах, потому что клиент может передать отрицательное число, которое неявно преобразуется в число без знака, и у меня нет никакого способа проверить его в моем методе. Обратитесь к статье Скотта Майера на эту тему здесь.
Итак, я должен передать в API целое число со знаком. Но как я могу получить самый большой целочисленный тип со знаком в системе? Есть ли typedef, похожий на size_t, который подписан? Или я должен просто использовать size_t вместо?
4 ответа
Но как я могу получить самый большой целочисленный тип со знаком в системе?
В C++11 <cstdint>
вы можете найти тип intmax_t
, который определен после стандарта C (7.20.1.5):
Следующий тип обозначает целочисленный тип со знаком, способный представлять любое значение любого целочисленного типа со знаком
Есть ли typedef, похожий на size_t, который подписан?
Нет, не в стандарте C++. POSIX определяет ssize_t
, но:
- это не предназначено для замены
size_t
(что само по себе также более ограничено POSIX) - не предназначен для хранения / передачи отрицательных значений, но для обозначения ошибки:
ssize_t
должен быть способен хранить значения, по крайней мере, в диапазоне [-1, {SSIZE_MAX}].
Итак, я должен передать в API целое число со знаком. (...) Или вместо этого я должен использовать size_t?
Если ваш интерфейс предназначен для работы с массивами C++, size_t
это единственный тип, который гарантируется стандартом, чтобы иметь возможность хранить любой из возможных индексов массива. Используя любой другой тип, вы можете (теоретически) потерять способность обращаться ко всему массиву (что даже отмечено в статье, на которую вы ссылались).
С помощью size_t
поэтому для целей индексирования это обычное явление - и используется многими библиотеками (включая STL).
Подписанный эквивалент size_t
это просто ssize_t
но этот тип не определен в стандарте C99, даже если он известен многим компиляторам.
Для стандарта C99 самый большой целочисленный тип со знаком определяется как intmax_t
,
Ссылка: 7. Библиотека / 7.18 Целочисленные типы / 7.18.1.5 Целочисленные типы наибольшей ширины
The standard type to use is std::intmax_t
который определен в <cstdint>
, To get the maximum value you can use std::numeric_limits<intmax_t>::max()
,
Образец кода:
#include <cstdint>
#include <iostream>
#include <limits>
int main(int argc, char* argv[]) {
std::cout << "max size = " << std::numeric_limits<intmax_t>::max() << std::endl;
}
Самый большой целочисленный тип со знаком в последних стандартах C и C++ long long
, Пока нет типа шире, чем long long
Вы всегда можете использовать это. Если вы хотите быть более ориентированным на будущее, используйте intmax_t
size_t
всегда typedef-ed для самого большого целого типа без знака в системе
Это неверно size_t
в 32-битных системах обычно также 32-битные, что, очевидно, не самый широкий тип возможного. Гарантируется, что он достаточно большой, чтобы представлять размер самого большого объекта в системе.
В случае size_t
нужно, ptrdiff_t
может использоваться как подписанный аналог. Но это не самый большой тип.
За
char
массивы корочеPTRDIFF_MAX
,std::ptrdiff_t
действует как подписанный аналогstd::size_t
: он может хранить размер массива любого типа и на большинстве платформ является синонимомstd::intptr_t