使用字节掩码防止符号扩展

时间:2012-05-06 19:01:24

标签: java networking bytearray endianness

我一直在阅读Java,第2版中的TCP / IP套接字。我希望能够更清楚地了解某些内容,但由于该书的网站没有论坛或任何内容,我想我会问这里。 在几个地方,本书使用字节掩码来避免符号扩展。这是一个例子:

private final static int BYTEMASK = 0xFF; //8 bits

public static long decodeIntBigEndian(byte[] val, int offset, int size) {
    long rtn = 0;
    for(int i = 0; i < size; i++) {
        rtn = (rtn << Byte.SIZE) | ((long) val[offset + i] & BYTEMASK);
    }
    return rtn;
}

所以这是我对正在发生的事情的猜测。如果我是对的,请告诉我。 二进制文件中的BYTEMASK应该看起来像00000000 00000000 00000000 11111111。 为了简单起见,我们只是说val字节数组只包含1个短数,因此偏移量为0.所以让我们将字节数组设置为val[0] = 11111111val[1] = 00001111。在i = 0rtn全为0,因此rtn << Byte.SIZE只保持值相同。然后有(long)val[0]因为符号扩展而使其全部为1个8字节。但是当你使用& BYTEMASK时,它会将所有额外的1设置为0,将最后一个字节保留为1。然后你得到rtn | val[0],它基本上翻转rtn的最后一个字节中的任何1。对于i = 1(rtn << Byte.SIZE)将最不重要的字节推过,并保留所有0。然后(long)val[1]使用所有零加00001111得到一个长的最低有效字节,这就是我们想要的。因此,使用& BYTEMASK不会改变它。然后,当使用rtn | val[1]时,它会将rtn的最低有效字节翻转为全1。最终返回值现在为rtn = 00000000 00000000 00000000 00000000 00000000 00000000 11111111 11111111。 所以,我希望这不会太久,这是可以理解的。我只是想知道我正在考虑这个问题的方式是否正确,而不仅仅是完全消除了逻辑。另外,让我感到困惑的一件事是BYTEMASK0xFF。在二进制文件中,这将是11111111 11111111,所以如果它被隐式转换为int,由于符号扩展,它实际上不是11111111 11111111 11111111 11111111吗?如果是这种情况,那么BYTEMASK如何工作对我来说没有意义。谢谢你的阅读。

1 个答案:

答案 0 :(得分:7)

除了最后一点,一切都是正确的:

0xFF已经是int0x000000FF),因此不会进行符号扩展。通常,Java中的integer number literalsint,除非它们以Ll结尾,然后它们为long s。