[英]Assign negative int to long in java
我有2个整数值存储在bytebuffer中,采用little-endian格式。 这些整数实际上是32位的长整数。 我将它们存储为类的成员变量, loBits
和hiBits
。
这就是我做的:
long loBits = buffer.getInt(offset);
long hiBits = buffer.getInt(offset + Integer.BYTES);
我想知道为什么直接将signed int分配给long是错误的。 我知道发生了什么,但真的很感激解释。
我从缓冲区读取的int是签名的(因为Java)。 如果它是负数,那么直接将其分配给long值(或者将其转换为(long)
)会将(long)
所有高阶位更改为有符号位值。
例如,对于int的十六进制表示, -1684168480
是9b9da0e0
。 如果我将此int分配给long,则所有更高阶32位将变为F
int negativeIntValue = -1684168480;
long val1 = negativeIntValue;
long val2 = (long) negativeIntValue;
十六进制表示:
negativeIntValue is 0x9b9da0e0
val1 is 0xffffffff9b9da0e0
val2 is 0xffffffff9b9da0e0
但是,如果我使用0x00000000FFFFFFFFL
屏蔽negativeIntValue
,我得到一个long,它具有与negativeIntValue
相同的十六进制表示和一个正长值2610798816
。
所以我的问题是:
是的,您的理解是正确的(至少如果我理解您的理解正确)。
发生这种情况的原因是(大多数)计算机使用2的补码来存储有符号值。 因此,当将较小的数据类型分配给较大的数据类型时,该值是符号扩展的,这意味着数据类型的多余部分将填充0或1位,具体取决于原始值是正还是负。
Java中的>>
和>>>
运算符之间的区别也是相关的。 第一个执行符号扩展(保持负值为负)第二个不执行(移动负值使其为正)。
原因是负值存储为二进制补码 。
为什么我们使用两个补码?
在固定宽度编号系统中,如果从0
减去1
,会发生什么?
0000b - 0001b -> 1111b
什么是下一个较小的数字为0
? 它是-1
。
因此,我们将所有位设置的二进制数(对于有符号数据类型)设置为-1
最大的优点是当从正数转为负数时,CPU不需要执行任何特殊操作。 它处理5 - 3
与3 - 5
相同
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.