buff.getInt()& 0xffffffffL是一个身份?

时间:2014-05-28 16:55:42

标签: java bit-manipulation bytebuffer

以下是我一直在关注的一些代码:

public static long getUnsignedInt(ByteBuffer buff) {
    return (long) (buff.getInt() & 0xffffffffL);
}

有没有理由buff.getInt() & 0xffffffffL0xffffffffL在32个最低有效位中有32位1?在我看来,结果总是buff.getInt()

3 个答案:

答案 0 :(得分:8)

简而言之,这是因为该方法需要将签名的 int(所有Java int都转换为无符号数量

如果您只是(long) buff.getInt(),而buff.getInt()返回-1,则最终会得到-1。这是签名数量 - 而不是该方法应该返回的数量。

因此,该方法所做的是通过将buff.getInt()位与int进行AND运算来强制0x00000000FFFFFFFF成为无符号。这有效地将签名的int的位“重新解释”为无符号int(实际上是有符号的long,但由于只有低32位将被设置,因此它可以作为无符号int),产生所需的结果。

例如,(为了简洁起见,使用字节)。

buff.getInt()确实是buff.getByte(),并返回-1 == 0xFF

尝试将其转换为int,由于符号扩展的魔力,您最终会得到0xFFFFFFFF - 仍为-1

但是,使用0xFF进行屏蔽,最后会得到0x000000FF == 255 - 所需的值。

相信显式演员是不必要的(它不在我的机器上),但我可能会遗漏某些东西......


编辑:实际上 是不必要的。来自JLS第5.6.2节:

应用扩展基元转换(第5.1.2节)来转换以下规则指定的一个或两个操作数:

  • 如果任一操作数的类型为double,则另一个操作数将转换为double
  • 否则,如果任一操作数的类型为float,则另一个操作数将转换为float
  • 否则,如果任一操作数的类型为long,则另一个操作数将转换为long
  • 否则,两个操作数都将转换为int类型。

答案 1 :(得分:3)

如果buff.getInt()为负数,则将其强制转换为长数时仍为负数。但它会被延长。

所以,如果你想保留比特模式,例如为了尝试将值解释为无符号值,&0xffffffffL将掩盖这些位。

e.g。如果buff.getInt()返回-2147483648,则返回的int将具有0x80000000的位模式。转为长,那仍然是-2147483648,但有点模式0xffffffff80000000。 0xffffffff80000000 & 0xFFFFFFFF保留原始位模式0x80000000

答案 2 :(得分:2)

Java中的整数(intlong)是已签名的two's complement个数字。这意味着如果数字为正数(或0),则高位数为0;如果数字为负数,则为-1。

要从int转换为long,Java会使用符号扩展名。这意味着它所填写的数字"左边依赖于最左边的数字。为了说明从4位到8位的数字:

  • 1 = 0001 - > 0000 0001
  • -1 = 1111 - > 1111 1111

因此,如果您想将1111解释为带符号的数字(即15),则无法将其从4位转换为8位:您将获得1111 1111 ,这是-1。你想要的是0000 1111,即15。

为此,您需要对数字执行按位AND以屏蔽已填入的高位,并将其转换为0。