Определены ли результаты поразрядных операций с целыми знаками?

Я знаю, что поведение >> в значении integer может быть зависимым от реализации (в частности, если левый операнд отрицательный).

Как насчет остальных: ~, >>, &, ^, |? Когда их операнды подписаны целыми числами встроенного типа (short, int, long, long long), гарантируются, что результаты будут одинаковыми (с точки зрения содержимого бит), как если бы их тип был неподписанным

Ответ 1

Для отрицательных операндов << имеет поведение undefined, а результат >> определяется реализацией (обычно как "арифметический" сдвиг вправо). << и >> концептуально не являются побитовыми операторами. Они представляют собой арифметические операторы, эквивалентные умножению или делению на соответствующую мощность из двух для операндов, на которых они хорошо определены.

Что касается истинных побитовых операторов ^, ~, | и &, они работают с битовым представлением значения в (возможно продвинутом) типе операнда. Их результаты хорошо определены для каждого возможного выбора подписанного представления (двухкомпонентное дополнение, дополнение или знак-величина), но в последних двух случаях возможно, что результат будет ловушечным представлением, если реализация рассматривает "отрицательный ноль", представление как ловушка. Лично я почти всегда использую беззнаковые выражения с побитовыми операторами, так что результат на 100% четко определен в терминах значений, а не представлений.

Наконец, обратите внимание, что этот ответ, как написано, применим только к C. C и С++ - очень разные языки, и, хотя я не знаю С++, я понимаю, что в некоторых из этих областей он может отличаться от C...

Ответ 2

  • Левый сдвиг << отрицательного значения имеет поведение undefined;
  • Правый сдвиг >> отрицательного значения дает результат, определенный реализацией;
  • Результат операторов &, | и ^ определяется в терминах поразрядного представления значений. Допускаются три возможности для представления отрицательных чисел в C: два дополнения, их дополнение и знак-величина. Метод, используемый реализацией, будет определять числовой результат, когда эти операторы используются для отрицательных значений.

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

Ответ 3

Содержимое бит будет одинаковым, но результирующие значения будут по-прежнему зависимыми от реализации.

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

Использование неподписанных типов избавляет вас от некоторых из этих проблем.

Ответ 4

В стандарте C89 определено поведение сдвинутых слева цифр, основанных на битовых позициях. Если ни подписанные, ни неподписанные типы не имеют битов заполнения, требуемое поведение для неподписанных типов в сочетании с требованием, чтобы положительные подписанные типы имели одно и то же представление, что и типы без знака, означало бы, что бит знака находится слева от самого значащего бита значения.

Это, в C89, -1 < 1 будет -2 на реализациях с двумя дополнениями, которые не имеют битов заполнения и -3 на реализациях с одним дополнением, которые не имеют битов заполнения. Если есть какие-либо реализации знаковой величины без битов заполнения, -1 < 1 будет равным 2. на них.

Стандарт C99 изменил левые сдвиги отрицательных значений на Undefined Поведение, но ничто в обосновании не дает подсказки относительно того, почему (или даже упоминает об изменении вообще). Поведение, требуемое C89, возможно, было менее идеальным в некоторых реализациях дополнения, и поэтому было бы разумно позволить этим реализациям свободу выбирать что-то лучшее. Я не видел никаких доказательств того, что авторы Стандарта не предполагали, что качественные реализации двух дополнений должны продолжать обеспечивать такое же поведение, как и C89, но, к сожалению, они на самом деле этого не говорили.