Требует ли стандарт C++, чтобы неотрицательный диапазон стандартного целочисленного типа со знаком был не меньше отрицательного диапазона?
РЕДАКТИРОВАТЬ: обратите внимание, что здесь я имею в виду неотрицательный диапазон, а не положительный диапазон, который, очевидно, на единицу меньше неотрицательного. > диапазон.
РЕДАКТИРОВАТЬ: Если мы предположим С++ 11, ответ будет "Да". Смотрите мои пояснения ниже. С точки зрения C++03 ответ, вероятно, "Нет".
Тот же вопрос можно задать следующим образом: гарантирует ли стандарт, что результат a - b
может быть представлен в стандартном целочисленном типе со знаком T
, предполагая, что и a
, и b
являются отрицательными значениями типа T
, и что a ≥ b
?
Я знаю, что стандарт допускает представление отрицательных значений с дополнением до двух, дополнением до единицы и величиной знака (см. С++ 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
либо оба отрицательные или оба неотрицательны.