Соответствует ли стандарт C ++ тому, что неотрицательное диапазон стандартного целочисленного типа со знаком, по крайней мере, такой же большой, как и отрицательный диапазон?
РЕДАКТИРОВАТЬ: Обратите внимание, что я имею в виду неотрицательное Диапазон здесь, а не положительный диапазон, который, очевидно, на один меньше, чем неотрицательное спектр.
РЕДАКТИРОВАТЬ: Если мы предположим, C ++ 11, ответ «Да». Смотрите мои разъяснения ниже. С точки зрения C ++ 03 ответ, вероятно, «Нет».
Тот же вопрос можно задать следующим образом: гарантирует ли стандарт, что результат a - b
представимо в стандартном целочисленном типе со знаком T
при условии, что оба a
а также b
являются отрицательный значения типа T
и что a ≥ b
?
Я знаю, что стандарт допускает представление отрицательных значений в виде дополнения до двух, дополнения до единицы и знаковой величины (см. C ++ 11, раздел 3.9.1 [basic.fundamental], пункт 7), но я не уверен, требует ли оно использования одного из этих трех представлений. Возможно нет.
Если мы примем одно из этих трех представлений и предположим, что нет никаких «ложных» ограничений ни в одном из двух диапазонов (отрицательном и неотрицательном), то действительно верно, что неотрицательный диапазон по меньшей мере равен большой, как отрицательный. Фактически, с дополнением до двух размер двух диапазонов будет равен, а с двумя другими представлениями размер неотрицательного диапазона будет на один больше, чем размер отрицательного.
Однако, даже если мы примем одно из упомянутых представлений, на самом деле недостаточно гарантировать что-либо о размере любого диапазона.
То, что я ищу здесь, это раздел (или набор разделов), который однозначно обеспечивает желаемую гарантию.
Любая помощь будет оценена.
Обратите внимание, что было бы достаточно чего-то подобного: Каждый бит в «слоте памяти» целого числа имеет одну и только одну из следующих функций:
У меня смутное воспоминание о том, что C99 что-то говорит в том же духе. Кто-нибудь знает что-нибудь об этом?
Хорошо, C99 (с TC3) предоставляет необходимые гарантии в разделе 6.2.6.2 «Целочисленные типы» параграфа 2:
Для целочисленных типов со знаком биты представления объекта должны быть разделены на три группы: биты значения, биты заполнения и бит знака. Там не должно быть никаких битов заполнения; должен быть ровно один знаковый бит. Каждый бит, который является битом значения, должен иметь то же значение, что и тот же бит в представлении объекта соответствующего типа без знака (если имеется M битов значения в типе со знаком и N в типе без знака, то M ≤ N). Если бит знака равен нулю, он не должен влиять на результирующее значение. Если бит знака равен единице, значение должно быть изменено одним из следующих способов:
- соответствующее значение со знаком бит 0 обнуляется (знак и величина);
- знаковый бит имеет значение — (2N ) (два дополнения);
- знаковый бит имеет значение — (2N — 1) (дополняют).
Что из этого применимо, определяется реализацией, как и то, является ли значение с знаковым битом 1 и всеми битами значения ноль (для первых двух) или со знаковым битом и всеми битами значения 1 (для дополнения единиц) представлением ловушки или нормальное значение. В случае знака, величины и их дополнения, если это представление является нормальным значением, оно называется отрицательным нулем.
Может кто-нибудь подтвердить, что эта часть C99 также является обязательной частью C ++ 11?
Я еще раз внимательно посмотрел как на стандарты C99, так и на стандарты C ++ 11, и стало ясно, что гарантии в параграфе 2 раздела 6.2.6.2 C99 также являются обязательными в C ++ 11.
C89 / C90 не дает таких же гарантий, поэтому нам нужен C99, что означает, что нам нужен C ++ 11.
Таким образом, C ++ 11 (и C99) предоставляет следующие гарантии:
Отрицательные значения в основных целых типах со знаком (стандарт + расширенный) должен быть представленным с использованием одного из следующих трех представлений: дополнение к двум, дополнение к двум или величина знака.
Размер неотрицательное диапазон один больше или равно размеру отрицательного диапазона для всех основных целых типов со знаком (стандарт + расширенный).
Вторая гарантия может быть пересчитана следующим образом:
-1 ≤ min<T> + max<T> ≤ 0
для любого основного целого типа со знаком T
(стандарт + расширенный) где min<T>
а также max<T>
являются сокращением для std::numeric_limits<T>::min()
а также std::numeric_limits<T>::max()
соответственно.
Кроме того, если мы предположим, что a
а также b
являются значениями того же самого или различных фундаментальных целочисленных типов со знаком (стандартные или расширенные), тогда следует, что a - b
хорошо определен и представлен в decltype(a - b)
пока a
а также b
либо оба отрицательны, либо оба неотрицательны.
Стандарт, кажется, не требует такой вещи, хотя я могу пропустить ключевые места. Все, что мы знаем о фундаментальных знаковых целочисленных типах, находится в 3.9.1 / 2:
Существует пять стандартных типов целых чисел со знаком: «знаковый символ», «короткий»
int »,« int »,« long int »и« long long int ». В этом списке каждый тип
обеспечивает как минимум столько же памяти, сколько и предшествующие ему в списке.
И в 3.9.1 / 7:
Типы bool, char, char16_t, char32_t, wchar_t, а также подписанные и
целочисленные типы без знака вместе называются целочисленными типами.48 A
синонимом целочисленного типа является целочисленный тип. Представления
целочисленные типы должны определять значения с использованием чистой двоичной нумерации
система.
Ни один из этих отрывков, кажется, ничего не говорит о соответствующих положительных и отрицательных диапазонах. Даже учитывая, что я не могу представить двоичное представление, которое бы не отвечало вашим потребностям.
Других решений пока нет …