Typedef для подписанного типа, который может содержать size_t?

Существует ли стандартный (или MSVC) тип typedef для подписанного типа, который может содержать полный диапазон значений size_t? То есть в 64-битной системе это будет 128-битное целое число со знаком.

Ответы

Ответ 1

Невозможно вообще определить такой тип. Совершенно законно для реализации сделать size_t самый большой поддерживаемый неподписанный тип, что означало бы, что ни один из подписанных типов не может содержать все его значения.

ptrdiff_t не обязательно достаточно широка. Это результат вычитания двух указателей, но нет ничего, что говорит, что вычитание указателя не может переполняться. См. Раздел 5.7 стандарта С++:

Когда два указателя на элементы одного и того же объекта массива вычитаются, результатом является разность индексов двух массивов элементы. Тип результата - это подписанная реализация. интегральный тип; этот тип должен быть того же типа, который определяется как std::ptrdiff_t в заголовке <cstddef> (18.2). Как и с любым другим арифметическое переполнение, если результат не помещается в предоставленное пространство, поведение undefined.

Самый большой подписанный тип - intmax_t, определенный в <stdint.h> или <cstdint>. Это функция C99, а С++ 11 - первый стандарт С++, который включает стандартную библиотеку C99, поэтому ваш компилятор может ее не поддерживать (и, скорее всего, MSVC этого не делает). Если существует тип подписанного типа, достаточно широкий для хранения всех возможных значений типа size_t, тогда intmax_t (хотя может быть и более узкий тип подписанного типа, который также квалифицируется).

Вы также можете использовать long long, который является подписанным типом, гарантированным как минимум 64 бита (и, скорее всего, такой же, как intmax_t). Даже если он недостаточно широк для хранения всех возможных значений типа size_t, он почти наверняка сохранит все соответствующие значения типа size_t - если только ваша реализация не поддерживает объекты размером более 8 экзабайт (это 8192 петабайт или 8388608 терабайт).

(Примечание. Я использую двоичные определения "exa-", "peta-" и "tera-", которые имеют сомнительную достоверность.)

Ответ 2

Я предполагаю, что вам нужен этот тип для какой-либо арифметики указателя. Очень маловероятно, что вам нужно что-то еще, кроме std::ptrdiff_t. Единственный случай, когда это будет играть роль на современной машине, - это когда вы находитесь в 32-битном режиме и работаете над набором данных с более чем 2 ^ 31 байтами. (Это будет невозможно даже в Windows без специальной работы.) Вы не сможете одновременно использовать два массива такого размера. В этом случае вы, вероятно, должны работать в 64-битном режиме.

В 64-битном режиме это, скорее всего, не будет проблемой в течение следующих 40 лет или около того с текущей скоростью развития памяти. И когда это становится проблемой, тогда скомпилируйте свой код в 128-битном режиме и он будет продолжать работать.;)

Ответ 3

Если вам нужен стандартный тип, который может содержать максимальное значение системы, может помочь <cstdint> (поскольку С++ 11).

Там typedef в этом заголовке, который содержит максимальный целочисленный тип ширины, тип intmax_t. intmax_t для целых чисел со знаком, а uintmax_t для беззнаковых - наибольшее целое, полностью поддерживаемое архитектурой.

Итак, предположим, что у вас 64-битная архитектура, следующая инструкция:

std::cout << "intmax_t is same int64_t? "
          << (std::is_same<intmax_t, int64_t>::value ? "Yes" : "No");

Будет выводиться:

intmax_t - тот же int64_t? Да

Живая демонстрация.

Надеюсь, что это поможет.