在C中表示负数?

时间:2010-10-17 05:17:56

标签: c language-lawyer negative-number twos-complement

C如何表示负整数?

是通过二进制补码表示还是使用MSB(最高有效位)?

十六进制中的

-1ffffffff

所以请为我澄清一下。

4 个答案:

答案 0 :(得分:41)

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位的int,并且当在这个32位int中使用时,忽略较低short的符号位。然后,作为32位有符号整数,在确定32位有符号int的值时会忽略一个填充位(在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 ++标准中quite a long way(WG21是负责此事的工作组),现在显然也被考虑用于C(由WG14)。

答案 1 :(得分:11)

C允许有符号整数的符号/幅度,一个补码和二进制补码表示。大多数典型硬件对整数使用二进制补码,对浮点使用符号/幅度(另一种可能性 - 浮点指数的“偏差”表示)。

答案 2 :(得分:7)

  十六进制中的

-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。

答案 3 :(得分:1)

对于整数类型,它通常是两个补码(特定于实现)。对于浮点数,有一个符号位。