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

elv*_*les 4 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;
}
Run Code Online (Sandbox Code Playgroud)

所以这是我对正在发生的事情的猜测.如果我是对的,请告诉我. BYTEMASK二进制应该看起来像00000000 00000000 00000000 11111111.为了简单起见,我们只说val字节数组只包含1个短路,因此偏移量为0.所以让我们将字节数组设置为val[0] = 11111111,val[1] = 00001111.在i = 0,全rtn是0,所以rtn << Byte.SIZE只保持值相同.然后(long)val[0]由于符号扩展而使其全部为1个8字节.但是当你使用时& BYTEMASK,它会将所有额外的1设置为0,将最后一个字节保留为1.然后你得到rtn | val[0]哪个基本上翻转在最后一个字节中的任何1 rtn.因为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来说甚至没有意义.谢谢你的阅读.

tru*_*ity 7

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

0xFF已经是int(0x000000FF),因此不会进行符号扩展.一般情况下,整数文字中的Java是int小号除非他们结束与一个Ll然后它们是long秒.