我在这里读过(https://stackoverflow.com/a/27762490/4415632)当发生整数溢出时,最重要的位被简单地切掉。
但是,我也在这里阅读(https://stackoverflow.com/a/27747180/3808877)当发生溢出时,"该值成为该类型的最小值,并再次开始向上计数。"哪一个是正确的,还是两个答案都是正确的?如果是这样,任何人都可以告诉我为什么这两种解释彼此相同吗?
答案 0 :(得分:2)
两者都是正确的,这取决于背景。一个是铸造的结果,一个是溢出的结果。这些是不同的操作。例如,如果您将Long.MAX_VALUE
投射到作为投射操作的int
System.out.println((int) Long.MAX_VALUE); // <-- -1
如果您通过向int
添加一个Integer.MAX_VALUE
来溢出System.out.println(Integer.MAX_VALUE + 1); // <-- Integer.MIN_VALUE
,那么
{{1}}
答案 1 :(得分:2)
这两种解释都是正确的,因为它们实际上是相同的。
让我们看一下数学,看看为什么。
Java以{em>二补码的格式将值存储在byte
,short
,char
,int
和long
中。
如果是byte
,short
,int
和long
,则已签名,如果char
为无符号。
二补码格式的一个属性是,对于大多数操作而言,该值是否被解释为 signed 或 unsigned 并不重要结果位模式将是相同的。
为了缩短内容,我将使用byte
进行解释,但其他类型的工作方式相同。
byte
有8位。最顶部的位被解释为 sign 位。所以,位模式是这样的:
snnn nnnn
分为两组,每组4位,称为半字节,并在此处执行以获得纯粹的可读性。作为旁注,半字节可以用十六进制数字表示。
因此,一个字节中有8位,每个位可以是0或1.这使我们得到2^8 = 256
个不同的值,可以存储在byte
中。
以下是一些示例值:
0000 0000 -> 0
0000 0001 -> 1
0000 0010 -> 2
0100 0000 -> 64
0111 1111 -> 127
1000 0000 -> -128
1111 1110 -> -2
1111 1111 -> -1
带符号的2的补码值是负的,即符号位置位,是通过取8位的正值并减去该范围来创建的,即在一个字节的情况下减去256。
现在让我们看看如果你采用-1
并添加1
会发生什么。
1111 1111 -1 / 255
+ 0000 0001 1
--------------
= 1 0000 0000 -0 / 256 intermediate result
= 0000 0000 0 / 256 result after dropping excess leading bits
有溢出。结果现在需要9位,但字节只有8位,因此最高位丢失。
让我们看另一个例子,-1
加-1
。
1111 1111 -1 / 255
+ 1111 1111 -1 / 255
--------------
= 1 1111 1110 -2 / 510 intermediate result
= 1111 1110 -2 / 254 result after dropping excess leading bits
或者,127
加5
。
0111 1111 127
+ 0000 0101 5
--------------
= 1000 0100 132 / -124
正如我们所看到的那样,前导位被丢弃,这实际上是通过“再次从最小值开始计数”导致其溢出的效果。
答案 2 :(得分:-2)
我添加了另一个选项:处理器陷阱。某些处理器会在整数溢出时生成陷阱。可用时,通常可以通过在处理器状态寄存器中设置一个位来在用户模式下启用此功能。