在TC ++编译器中, 5 的二进制表示为(00000000000000101)。 我知道负数存储为2的补码,因此二进制的 -5 是(111111111111011)。最高位(符号位)为1,表示它是负数。
那么编译器如何知道 -5 ?如果我们将(111111111111011)上面给出的二进制值解释为无符号数,它会变得完全不同吗?
另外,为什么1赞美 5 -6(1111111111111010)?
答案 0 :(得分:8)
编译器不知道。如果您将-5
投放到unsigned int
,则会获得32763
。
答案 1 :(得分:5)
编译器知道,因为这是CPU本身使用的约定。您的计算机有一个CPU,以二进制补码表示法存储负数,因此编译器也会如此。如果你的CPU支持一个补码表示法,那么编译器就会使用它(顺便说一下,就像IEEE浮点数一样)。
关于该主题的维基百科文章解释了two's complement符号的工作原理。
答案 2 :(得分:3)
处理器实现有符号和无符号指令,这些指令将以不同的二进制数表示方式运行。编译器根据所涉及的操作数的类型(即int
与unsigned int
)知道要发出哪些指令。
编译器不需要知道数字是否为负数,它只是为所涉及的类型发出正确的机器或中间语言指令。处理器或运行时对这些指令的实现通常并不在乎数字是否为负数,因为二进制补码运算的公式对于正数或负数都是相同的(实际上,这是主数据)二进制补码算法的优点)。 需要知道数字是否为负数将类似于printf()
,正如Andrew Jaffe指出的那样,设置的MSBit表示二进制补码中的负数。
答案 3 :(得分:2)
第一位仅设置为负数(称为符号位)
详细信息可用here
答案 4 :(得分:2)
两个补码的kewl部分是机器语言Add和Subtract指令可以忽略所有这些,只做二进制算术而且它只是有效...
即,-3 + 4
二进制2补码中的是
1111 1111 1111 1101 (-3)
+ 0000 0000 0000 0100 ( 4)
-------------------
0000 0000 0000 0001 ( 1)
答案 5 :(得分:2)
让我们举个例子: 我们在二进制中有两个字节的两个数字: A = 10010111 B = 00100110 (请注意,该机器不知道此级别中有符号或无符号的概念)
现在当你说“添加”这两个时,机器是什么?它只是添加:
R = 10111101(并且位:1)
现在,我们 - 编译器 - 需要解释操作。我们有两个选择:数字可以是签名或无签名。
1- unsigned case:在c中,数字的类型为“unsigned char”,值为151和38,结果为189.这是微不足道的。
2 - 签名案例:我们编译器根据msb解释数字,第一个数字是-105,第二个数字仍然是38.所以-105 + 38 = -67。但-67是10111101。但这是我们在结果(R)中已经有的!结果是一样的,唯一的区别是编译器如何解释它。
结论是,无论我们如何考虑数字,机器都会对数字执行相同的操作。但编译器将依次解释结果。
请注意,并非知道2补码概念的机器。它只是添加两个数字而不关心内容。 编译器然后查看符号位,决定。
当涉及减法时,这次再次,操作是唯一的:取第二个数字的2的补码并加上两个。
答案 6 :(得分:1)
如果数字被声明为有符号数据类型(而不是类型转换为无符号类型),则编译器将知道,当符号位为1时,它是负数。至于为什么使用2的补码而不是1的补码,你不希望能够得到-0的值,1的补码允许你这样做,所以他们发明了2的补码来解决这个问题。
答案 7 :(得分:0)
正是那个最重要的位 - 如果你知道一个数字被签名,那么如果MSB = 1,编译器(和运行时!)知道将它解释为负数。这就是为什么类似c的语言有整数(正数和负数)和无符号整数的原因 - 在这种情况下,你将它们全部解释为正数。因此,有符号字节从-128到127,但是从0到255的无符号字节。