1s2*_*e7v 22 c negative-number twos-complement language-lawyer
C如何表示负整数?
它是通过二进制补码表示还是使用MSB(最重要的位)?
-1
十六进制是ffffffff
.
所以请为我澄清一下.
pax*_*blo 42
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
Run Code Online (Sandbox Code Playgroud)
(a)有趣的是,鉴于实际使用其他两种方法的现代实现的稀缺性,已经推动将两个补码接受为一种真正的方法.这在C++标准中已经走了很长的路(WG21是负责这个的工作组),现在显然也被考虑用于C(由WG14).
十六进制中的-1是ffffffff.所以请在这方面澄清我.
在二进制补码(迄今为止最常用的表示)中,除最高有效位(MSB)之外的每个位,从右到左(递增的数量级)具有值2 n,其中n从零增加1.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)
Run Code Online (Sandbox Code Playgroud)
其中[1]是丢弃的进位.另一个例子; 10 - 11 == 10 +( - 11):
0000 1010
+1111 0101
---------
1111 1111 = -1 (decimal)
Run Code Online (Sandbox Code Playgroud)
二进制补码的另一个特点是它有一个代表零的值,而符号量和一个补码各有两个; +0和-0.