Почему результат "-10 & 5" равен 4?Что происходит, когда побитовое И применяется к отрицательным числам? - PullRequest
0 голосов
/ 27 мая 2019

Я написал и скомпилировал следующий код:

void main()
{ 
    printf("%d", -10 & 5);
}

Когда я запускаю его, он выводит значение 4. Почему вывод этой программы 4?

1 Ответ

6 голосов
/ 27 мая 2019

В C в результате двоичного кода & каждый бит зависит от двух соответствующих битов в операндах. Если бит в одной и той же позиции установлен (1) в обоих операндах, он устанавливается в результате. Если это ясно (0) в любом операнде, это ясно в результате. Например, если заданы биты 0011 и 0101, оператор & выдаст 0001, потому что только в последней позиции бит установлен в обоих операндах.

Вы, вероятно, уже знаете, что положительные целые числа представлены двоичным кодом. Позиции битов нумеруются начиная с 0 справа, затем 1 для следующей позиции, 2, 3 и так далее. Бит в позиции i представляет значение 2 i , поэтому бит 0 представляет 1, бит 1 представляет 2, бит 2 представляет 4, бит 3 представляет 8 , бит 4 представляет 16 и так далее. Значение, представленное всеми битами, является суммой значений битов, которые установлены в 1. Таким образом, 101 представляет 5, потому что биты для 2 2 = 4 и 2 0 = 1 установлены, а 4 + 1 = 5.

Стандарт C определяет три правила, которые реализация C может использовать для представления отрицательных чисел (в C 2018 6.2.6.2 2):

  • Один из битов представляет знак. Если бит знака равен 0, значение такое же, как указано выше. Если бит знака равен 1, значение отменяется. Итак, если первый бит является знаковым битом, то 5 - это 0101, это 5, а -5 - это 1101. Это называется знак и величина .
  • Один из битов представляет знак, и, если число отрицательное, все биты инвертируются. Итак, 5 это 0101, а -5 это 1010. Это называется дополнение .
  • Один из битов представляет знак, и, если число отрицательное (назовем его x ), биты устанавливаются в шаблоне, который будет использоваться для 2 N - x , где N - количество битов. Например, для четырех битов 2 N = 16, и 5 равно 0101, а -5 представлен битами для 16-5 = 11, которые равны 1011. Это называется два дополнения .

В ранних компьютерных аппаратных и программных средствах все вышеперечисленное было опробовано. Последнее, дополнение двух, является доминирующим в современных вычислениях для целых чисел. (Большинство чисел с плавающей точкой использует знак и величину.) Тем не менее, стандарт C по-прежнему разрешает реализациям использовать любой из методов.

Из-за этого результат -10 & 5 зависит от реализации. Я проиллюстрирую использование восьми битов с пробелом, чтобы сгруппировать их в два набора по четыре бита для наглядности:

С двумя дополнениями:

  • −10 обозначено 1111 0110 (256 - 10 = 246 = 128 + 64 + 32 + 16 + 4 + 2), 5 использует 0000 0101, а −10 & 5 равно 0000 0100, что соответствует 4.

С дополнением:

  • −10 обозначено 1111 0101, 5 использует 0000 0101, а −10 & 5 равно 0000 0101, что соответствует 5.

со знаком и величиной:

  • −10 представлен 1000 1010, 5 использует 0000 0101, а -10 & 5 равен 0000 0000, что соответствует 0.

Таким образом, реализация C, соответствующая стандарту C, может выдавать 0, 4 или 5 для -10 & 5, но 4 является наиболее распространенным результатом.

...