Что происходит, когда побитовое И применяется к отрицательным числам?

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

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

person Sonic-BO_oM    schedule 27.05.2019    source источник
comment
Вы знаете, что такое оператор &?   -  person Jabberwocky    schedule 27.05.2019
comment
@Sonic-BO_oM, каким, по-вашему, должен быть результат?   -  person Sandy    schedule 27.05.2019
comment
Запустите программу, чтобы увидеть, что это такое. Затем прочитайте об en.wikipedia.org/wiki/Bitwise_operations_in_C#Bitwise_AND_&.   -  person klutt    schedule 27.05.2019
comment
@Broman: Запуск программы не отвечает на вопрос, почему вывод равен 4, и не гарантирует, что вывод будет равен 4 в каждой реализации C. (В общем случае запуск программы даже не гарантирует, что полученный результат будет таким же, как при каждом выполнении программы в той же реализации C.) Кроме того, информации об операторе побитового И недостаточно для ответа на вопрос: поскольку результат также зависит от того, как числа представлены с помощью битов.   -  person Eric Postpischil    schedule 27.05.2019
comment
Этапы анализа: поиск оператора &. Ага... Теперь найдите битовую комбинацию числа -10 и числа 5. Теперь выясним, каков результат применения оператора &. Вот что будет напечатано.   -  person Paul Ogilvie    schedule 27.05.2019
comment
@PaulOgilvie: Где можно найти битовую комбинацию числа -10?   -  person Eric Postpischil    schedule 27.05.2019
comment
@EricPostpischil, из бумаги, на которой вы это записываете, или из отладчика.   -  person Paul Ogilvie    schedule 27.05.2019
comment
@EricPostpischil Правда, недостаточно правильно ответить на вопрос, но эти две вещи все равно нужно было сделать до публикации вопроса. Я как бы объяснил, почему я проголосовал за это из-за отсутствия исследований.   -  person klutt    schedule 27.05.2019
comment
А отрицательные числа имеют другую битовую структуру. Они находятся в форме дополнения 2. См. en.wikipedia.org/wiki/Two%27s_complement.   -  person J...S    schedule 27.05.2019
comment
@PaulOgilvie: я написал «−10» на листе бумаги. Битовый шаблон не появился. Что вы хотели этим сказать, непонятно. В отладчике lldb «print -10» показывает «-10», а не битовый шаблон.   -  person Eric Postpischil    schedule 27.05.2019
comment
@Sonic-BO_oM Вот хорошая статья на эту тему: wiki.sei.cmu.edu/confluence/display/c/   -  person klutt    schedule 27.05.2019
comment
@J...S: отрицательные числа не всегда представляются таким образом. Вы и другие просто распространяете знания, которые вы уже узнали, не задумываясь о шагах, которые должен пройти тот, кто не знает этих знаний, чтобы получить их. Вы считаете «очевидным» то, что на самом деле вовсе не очевидно. Как только вы действительно соберете воедино всю информацию, которую на самом деле необходимо объяснить, чтобы объяснить вопрос, у вас будет ответ, который следует опубликовать как ответ, а не комментарий.   -  person Eric Postpischil    schedule 27.05.2019
comment
О, @EricPostpischil, я дал тебе более высокую оценку. Может быть, посмотреть на другую сторону бумаги?   -  person Paul Ogilvie    schedule 27.05.2019
comment
@EricPostpischil Какими еще способами представляются отрицательные числа? И используются ли эти методы до сих пор? Я просто спрашиваю, потому что не знаю.   -  person J...S    schedule 27.05.2019
comment
@J...S Здесь вы можете прочитать о различных методах en.wikipedia.org/wiki/Signed_number_representations   -  person klutt    schedule 27.05.2019
comment
@J...S: я объяснил их в своем ответе. И дополнение до двух, и знак и величина по-прежнему широко используются, но знак и величина в основном используются только для операций с плавающей запятой. На самом деле, с плавающей запятой обычно используются два метода одновременно: знак и величина для целого числа и двоичное смещение для экспоненты.   -  person Eric Postpischil    schedule 27.05.2019


Ответы (1)


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

Вы, вероятно, уже знаете, что положительные целые числа представлены в двоичном формате. Битовые позиции нумеруются, начиная с 0 справа, затем 1 для следующей позиции, 2, 3 и так далее. Бит в позиции i представляет собой значение 2i, поэтому бит 0 представляет 1, бит 1 представляет 2, бит 2 представляет 4, бит 3 представляет 8, бит 4 представляет 16 и так далее. Значение, представленное всеми битами, представляет собой сумму значений битов, для которых установлено значение 1. Таким образом, 101 представляет 5, поскольку биты для 22 = 4, а 20 = 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), биты устанавливаются в шаблоне, который будет использоваться для 2N< /em>-x, где N — количество бит. Например, для четырех битов 2N = 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 является наиболее распространенным результатом.

person Eric Postpischil    schedule 27.05.2019