Intereting Posts
Найти n наибольших элементов из массива Принять числовые значения только для ввода с помощью scanf Компиляция-ошибки: «создание массива с отрицательным размером (‘-0x00000000000000001’)», «назначение местоположения только для чтения» Невозможно понять. Давайте ставим пример статического кластера хранения Включить внешнюю библиотеку в C Основы работы с несколькими клиентскими серверами UDP C Word Count программа Как хранить ключи ассоциативного массива в C, реализованные через hcreate / hsearch по значению (не по ссылке)? Как создать общую библиотеку с помощью ld? ncurses – изменение размера Зачем использовать _mm_malloc? (в отличие от _aligned_malloc, alligned_alloc или posix_memalign) Доступ к определенным местам памяти в C Как я могу реализовать hash-файл фиксированного размера? Почему сдвиги имеют более низкий приоритет, чем сложение и вычитание в C? Атрибуты перечислителя в GCC

Как C обрабатывает число 0 в архитектуре комплемента?

Недавно я изучал систему комплемента представления чисел и из того, что я понимаю, есть два варианта числа 0. Существует отрицательный нуль (-0) и положительный нуль (+0).

Мой вопрос заключается в том, что в своей архитектуре дополнений, как именно эта аномалия рассматривается в C? C делает различие между -0 и +0 или обе эти формы просто обрабатываются как ноль.

Если это так, что оба значения +0 и -0 возвращают TRUE при проверке на ноль, то мне интересно, как будет работать следующий пример кода, который вычисляет количество заданных битов в целых числах, если мы вводим -0 в качестве его ввода.

int bitcount(int x) { int b; for (b = 0; x != 0; b++) x &= (x-1); return b; } 

Поскольку -0, в своем дополнении, имеет все свои биты, установленные в 1, -0, должны возвращать наибольшее количество бит, установленных из любого другого числа; однако, похоже, что этот код завершит проверку состояния цикла x != 0 и даже не войдет в цикл, давая неверный результат.

Было бы возможно каким-то образом в C в архитектуре дополнений сделать условие цикла чувствительным к положительным нулям, как в: x != +0 Кроме того, если бы я вычитал 1 из +0, я бы получил -0 или – 1. Другими словами, +0 – 1 = -0 в архитектуре дополнений?

В целом, чтобы не заходить слишком далеко в этом обсуждении, мне просто интересно, как C рассматривает особенности числа 0 в архитектуре дополнения.

Определяется реализация, будь то в архитектуре с одним дополнением значение «со знакомным битом и всеми битами значений 1» является «представлением ловушки» или нормальным значением. Если это ловушка, любая попытка сделать что-либо с ней или даже создать ее, в первую очередь, вызывает неопределенное поведение. Если это нормальное значение, это «отрицательный ноль», и есть явный список операций, которые разрешены для его создания:

Если реализация поддерживает отрицательные нули, они должны генерироваться только:

  • операторы &, |, ^, ~, << и >> с операндами, которые производят такое значение;
  • операторы +, -, *, / и%, где один операнд является отрицательным нулем, а результат равен нулю;
  • на основе описанных выше случаев.

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

(C11 / N1570, раздел 6.2.6.2, пункт 3).

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

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

Тем не менее, весь вопрос спорный, потому что никто не производил процессор без двухкомпонентности не менее 25 лет. Можно надеяться, что будущий пересмотр стандарта C перестанет допускать такую ​​возможность; это упростило бы многие вещи.

Чтобы ответить на ваш вопрос, есть две возможности рассмотреть:

  • если битовый шаблон со всеми установленными битами является представлением ловушки (которое явно разрешено стандартом C), передача такого значения функции имеет неопределенное поведение.

  • если этот бит-шаблон разрешен, это дополнение к представлению отрицательного нуля , которое должно сравниваться с 0 . В этом случае функция, записанная, будет определять поведение и будет возвращать 0 поскольку тест начального цикла является ложным.

Результат был бы другим, если бы функция была написана следующим образом:

 int bitcount32(int x) { // naive implementation assuming 31 value bits int count = 0, b; for (b = 0; b < 31; b++) { if (x & (1 << b)) count++; } } return count; } 

В этой дополнительной архитектуре bitcount32(~0) будет оцениваться до 31 :

(x & (1 << b)) с x аргумент с конкретным битовым шаблоном и b в диапазоне для 1 << b должен быть определен, оценивается как 1 << b , другое значение из результата на двух дополнениях и знаках / магнитудой.

Обратите внимание, однако, что опубликованная реализация имеет неопределенное поведение для аргумента INT_MIN поскольку x-1 вызывает подписанное арифметическое переполнение. Целесообразно всегда использовать неподписанные типы для побитовых и сдвиговых операций.