C如何表示负整数?
是通过二进制补码表示还是使用 MSB(最高有效位)?
-1
十六进制是ffffffff
.
所以请为我澄清这一点。
C如何表示负整数?
是通过二进制补码表示还是使用 MSB(最高有效位)?
-1
十六进制是ffffffff
.
所以请为我澄清这一点。
ISO C(C99 section 6.2.6.2/2
在这种情况下,但它延续到标准(a)的后续迭代)声明实现必须为整数数据类型选择三种不同的表示形式之一,二进制补码,一个补码或符号/大小(尽管它令人难以置信可能两者的互补实现远远超过其他实现)。
在所有这些表示中,正数是相同的,唯一的区别是负数。
要获得正数的负表示,您:
您可以在下表中看到这一点:
号码 | 二进制补码| 补码| 符号/大小 =======|======================|==================== =|===================== 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 位的 short(每个都有自己的符号位)组成一个 32 位的 int,并且在这个 32 位的 int 中使用时忽略低位 short 的符号位。然后,作为 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)。
C 允许有符号整数的符号/大小、一个补码和二进制补码表示。大多数典型的硬件对整数使用二进制补码,对浮点使用符号/幅度(还有另一种可能性——浮点指数的“偏差”表示)。
十六进制的 -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。
对于整数类型,它通常是二进制补码(特定于实现)。对于浮点数,有一个符号位。