0

我有一种 int 和一种 uint 类型:

int tempA = 0xbc000669;
uint tempB = 0xbc000669;

当我做

tempA /0x2000,想向右移动 13,它给了我0xfffde001

尽管

tempB / 0x2000,也想向右移动 13,它给了我正确的答案:0x0005e000

任何人都知道为什么有一个签名的部门,我得到一个错误的答案?我没想到除法会溢出?谢谢

4

4 回答 4

4

在声明中

tempA / 0x2000

编译器会看到一个 int 类型的变量和一个数字文字值。由于 int 类型的除法需要两个 int 类型的操作数,因此值 0x2000 也会自动转换为 int。该语句评估为

(int)0xbc000669 / (int)0x2000

即 -1140849047 / 8192 等于 -139263

十六进制的 -139263 是 FFFDE001(至少在 32 位值上)

于 2013-09-25T18:44:34.143 回答
1

0xbc000669实际上不能包含在 a 中int,更准确地说它将代表 a negative integer。我们知道anint使用32nd bit. sign bitWhile0cbc000669具有最重要的半字节,因为0xb它等于1011-> 32nd bitis1并且实际整数是负数。所以:

int tempA = 0xbc000669;

tempA等于-1140849047,将此数字右移 13 位二进制数字将返回您得到的确切结果:0xfffde001.

如果你这样声明你tempBuint

uint tempB = 0xbc000669;

它可以完全包含在 a 中,uint因为uint不使用 the32nd bit作为符号位。实际数字是 a positive integer,它的值是3154118249,将此值右移 13 位二进制数字将为您提供准确的结果0x5e000

于 2013-09-25T20:53:26.493 回答
0

解释这一点的最好方法是展示这些位是如何工作的。 关于签名数字表示的维基百科文章很好地涵盖了它。您需要阅读关于二进制补码的部分。

我认为,人们希望 -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

那么现在让我们看看你得到的答案。在有符号除法中,当您向右移动时,您实际上最终会用 1 填充数字的左侧,然后加 1。这正是您在结果中看到的。

0xFFFDE001 = 1111 1111 1111 1101 1110 0000 0000 0001
0x0005E000 = 0000 0000 0000 0101 1110 0000 0000 0000

正如您会注意到的,它们都是相同的,除了顶部的(来自您签名的部门)在左侧填充了 13 个 1,并在末尾添加了 1。

有符号整数要记住的重要一点是二进制补码会改变位的顺序,因此,不包括符号位,-50 与 +50 的位模式不同。

于 2013-09-25T19:03:39.140 回答
0

从规范中关于整数除法的简介:

除法将结果向零舍入,结果的绝对值是小于两个操作数的商的绝对值的最大可能整数。当两个操作数具有相同符号时,结果为零或正,当两个操作数具有相反符号时,结果为零或负。

如果我正确解释该文本,则会导致:在第一个示例中,有符号的 int 值设置了符号位;第二个数字 (0x2000) 为正数,因此结果为零或负数。

于 2013-09-25T18:39:51.967 回答