我有一个int和一个uint类型:
int tempA = 0xbc000669;
uint tempB = 0xbc000669;
当我做的时候
tempA /0x2000
,想要向右移动13,它会给我0xfffde001
,而
tempB / 0x2000
,想要向右移动13,它给了我正确答案:0x0005e000
任何人都知道为什么有签名的部门,我得到一个错误的答案?我不认为师可能会溢出?感谢
答案 0 :(得分:4)
声明
tempA / 0x2000
编译器会看到int类型的变量和数字文字值。由于int类型的除法需要两个int类型的操作数,因此值0x2000也会自动转换为int。该陈述评估为
(int)0xbc000669 / (int)0x2000
是 -1140849047 / 8192并等于-139263
-139263(十六进制)是FFFDE001(至少32位值)
答案 1 :(得分:1)
0xbc000669
实际上{strong}中的不能包含,更准确地说它代表int
。我们知道negative integer
使用int
作为32nd bit
。虽然sign bit
最重要的半字节为0cbc000669
,但等于0xb
- > 1011
为32nd bit
,实际整数为负数。所以:
1
会使int tempA = 0xbc000669;
等于tempA
,右移这个数字的13位二进制数字将返回您得到的确切结果:-1140849047
。
如果您将0xfffde001
声明为tempB
,请执行以下操作:
uint
它可以完全包含在uint tempB = 0xbc000669;
中,因为uint
不使用uint
作为符号位。实际数字为32nd bit
,其值为positive integer
,右移此值为13位二进制数字将为您提供3154118249
答案 2 :(得分:0)
关于整数除法的规范中的模糊:
除法将结果舍入为零,结果的绝对值是小于两个操作数的商的绝对值的最大可能整数。当两个操作数具有相同的符号时,结果为零或正,当两个操作数具有相反的符号时,结果为零或负。
如果我正确地解释了该文本,则会导致这种情况:在第一个示例中,signed int值设置了符号位;第二个数字(0x2000)为正数,因此结果为零或负数。
答案 3 :(得分:0)
解释这个的最好方法是展示这些位是如何工作的。 The Wikipedia关于签名号码的文章很好地涵盖了它。你想阅读关于二重补语的部分。
我认为,期望人们希望-1和1的二进制文件是相同的,除了符号位为1表示-1。不是这种情况。例如,1是
0000 0000 0000 0000 0000 0000 0000 0001
而-1是
1111 1111 1111 1111 1111 1111 1111 1111
人们会直觉地认为-1实际上是-127:
-127 == 1000 0000 0000 0000 0000 0000 0000 0001
现在让我们来看看你得到的答案。在签名的分区中,当你向右移动时,你实际上最终用1s填充数字的左侧,并添加1.这正是你对结果的看法。
0xFFFDE001 = 1111 1111 1111 1101 1110 0000 0000 0001
0x0005E000 = 0000 0000 0000 0101 1110 0000 0000 0000
正如你会注意到的那样,它们都是相同的,除了顶部的一个(来自你签名的部门)左边有13个填充,最后加1个。
使用有符号整数要记住的重要一点是,两个补码会改变位的排序,因此,除了符号位,-50与+50的位模式不同。