Представление отрицательных чисел в C? - PullRequest
22 голосов
/ 17 октября 2010

Как C представляет отрицательные целые числа?

Является ли это представлением дополнения до двух или с использованием MSB (старший значащий бит)?

-1 в шестнадцатеричном формате ffffffff.

Поэтому, пожалуйста, уточните это для меня.

Ответы [ 4 ]

41 голосов
/ 17 октября 2010

ISO C (C99 section 6.2.6.2/2 в данном случае, но он переносит на более поздние итерации стандарта (a) ), в котором указывается, что реализация должна выбрать одно из трех различных представлений для целочисленных типов данных, дополнение к двум , дополнение или знак / величина (хотя невероятно вероятно, что реализации дополнения двух намного перевешивают другие).

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

Чтобы получить отрицательное представление для положительного числа, вы:

  • инвертировать все биты, затем добавить один для дополнения до двух.
  • инвертировать все биты для дополнения.
  • инвертировать только бит знака для знака / величины.

Вы можете увидеть это в таблице ниже:

number | two's complement    | ones' complement    | sign/magnitude
=======|=====================|=====================|====================
     5 | 0000 0000 0000 0101 | 0000 0000 0000 0101 | 0000 0000 0000 0101
    -5 | 1111 1111 1111 1011 | 1111 1111 1111 1010 | 1000 0000 0000 0101

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

Предположим, что машина использует пару 16-битных шорт (каждая со своим собственным знаковым битом) для создания 32-битного целого числа, а знаковый бит нижнего короткого замыкания игнорируется при использовании в этом 32-битном целом. Затем, как 32-разрядное знаковое целое, существует бит дополнения (в середине 32-разрядного), который игнорируется при определении значения 32-разрядного знакового целого. Но если этот 32-битный элемент обрабатывается как 32-битное беззнаковое целое, то этот бит дополнения виден программе пользователя. Комитету C было сказано, что есть машина, которая работает таким образом, и это одна из причин, по которой биты заполнения были добавлены в C99.

Я полагаю, что машина, о которой они, возможно, имели в виду, была Datacraft 6024 (и это наследники из Harris Corp). В этих машинах у вас было 24-битное слово, используемое для целого числа со знаком, но, если вы хотели получить более широкий тип, два из них были объединены в 47-битное значение, а знаковый бит одного из слов игнорировался:

+---------+-----------+--------+-----------+
| sign(1) | value(23) | pad(1) | value(23) |
+---------+-----------+--------+-----------+
\____________________/ \___________________/
      upper word            lower word

(a) Интересно, что с учетом нехватки современных реализаций, которые на самом деле используют два других метода, был толчок к принятию дополнения до двух в качестве одного истинного метода. Это прошло довольно длинный путь в стандарте C ++ (WG21 - рабочая группа, ответственная за это) и теперь, очевидно, рассматривается и для C (WG14).

11 голосов
/ 17 октября 2010

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

7 голосов
/ 17 октября 2010

-1 в шестнадцатеричном формате - это ffffffff.Поэтому, пожалуйста, разъясните мне в этом отношении.

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

Так, например, в 8-битном целом числе, дополняющем двойное число, MSB имеет значение места -2 7 (-128), поэтому двоичное число: 1111 1111 2 равно -128 + 0111 1111 2 = -128 + 127 = -1

Одна полезная особенность двухдополнение состоит в том, что ALU процессора требует только блока сумматора для выполнения вычитания, формируя дополнение двух правого операнда.Например, 10 - 6 эквивалентно 10 + (-6);в 8-битном двоичном коде (для простоты объяснения) это выглядит так:

   0000 1010
  +1111 1010
   ---------
[1]0000 0100  = 4 (decimal)

Где [1] - отброшенный бит переноса.Другой пример;10 - 11 == 10 + (-11):

   0000 1010
  +1111 0101
   ---------
   1111 1111  = -1 (decimal)

Другая особенность дополнения к двум состоит в том, что у него есть одно значение, представляющее ноль, тогда как у знака-величины и дополнения каждого есть два;+0 и -0.

1 голос
/ 17 октября 2010

Для целочисленных типов это обычно два дополнения (зависит от реализации). Для плавающей запятой есть знаковый бит.

...