Что означает "производить отрицательные нули" в системе, которая его не поддерживает?

C17 6.2.6.2/4 говорит:

Если реализация не поддерживает отрицательные нули, поведение операторов &, |, ^, ~, << и >> с операндами, которые могли бы создать такое значение, не определено.

Если у меня есть система с 2 дополнениями, она не поддерживает отрицательные нули. И он всегда использует все возможные комбинации двоичного числа, чтобы выразить значение. Поэтому невозможно получить отрицательный ноль независимо от того, какая битовая операция используется. Так в чем же смысл этого текста?

Я предполагаю, что эта часть относится к системам с 1 дополнением или величиной со знаком, которые не поддерживают отрицательные нули, но вместо этого используют бит дополнения или представление прерывания. Это правильно?

Ответ 1

Ваша интерпретация верна.

Переходя к пункту 2 пункта 6.2.6.2:

Для целочисленных типов со знаком биты представления объекта должны быть разделены на три группы: биты значения, биты заполнения и бит знака. Там не должно быть никаких битов заполнения; знаковый символ не должен иметь никаких битов заполнения. Должен быть ровно один знаковый бит. Каждый бит, который является битом значения, должен иметь то же значение, что и тот же бит в представлении объекта соответствующего типа без знака (если имеется M битов значения в типе со знаком и N в типе без знака, то M ≤ N). Если бит знака равен нулю, он не должен влиять на результирующее значение. Если бит знака равен единице, значение должно быть изменено одним из следующих способов:

  • соответствующее значение со знаком бит 0 обнуляется (знак и величина);
  • знаковый бит имеет значение - (2 М) (дополнение по два);
  • знаковый бит имеет значение - (2 M - 1) (дополняется).

Что из этого применимо, определяется реализацией, так как является ли значение с битом знака 1 и всеми битами значения ноль (для первых двух), или с битом знака и всеми битами значения 1 (для единиц), является представлением прерывания или нормальное значение. В случае знака и величины и единиц дополняют, если это представление является нормальным значением, оно называется отрицательным нулем.

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

В качестве примера, предположим, что система имеет представление знака и величины и 32-битное int без заполнения. Тогда представление, которое будет отрицательным нулем, если оно поддерживается, будет 0x80000000.

Теперь предположим, что выполняются следующие операции:

 int x = 0x7fffffff;
 x = ~x;

Если реализация поддерживает отрицательный ноль, оператор ~ сгенерирует -0 как результат и сохранит его в x. Если это не так, он создает представление ловушки и вызывает неопределенное поведение в соответствии с пунктом 4.

Ответ 2

Да, я думаю, что ваша интерпретация верна. В двух дополнениях, это не операции, которые могли бы генерировать отрицательный ноль, потому что концепция здесь не существует: любое значение, для которого установлен бит знака, обязательно меньше 0.

Кстати: очень вероятно, что экзотические знаки будут удалены из C2x, поэтому все это исчезнет.