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