使用0xff进行安慰,需要澄清

时间:2012-03-30 20:15:32

标签: java bit-manipulation

在以下代码段中,考虑将第8行替换为注释等效

1. private static String ipToText(byte[] ip) {
2.  StringBuffer result = new StringBuffer();
3.
4.  for (int i = 0; i < ip.length; i++) {
5.      if (i > 0)
6.          result.append(".");
7.
8.      result.append(ip[i]); // compare with result.append(0xff & ip[i]);
9.  }
10.
11.     return result.toString();
12. }

.equals()测试确认添加0xff不会改变任何内容。是否有理由应用此蒙版?

4 个答案:

答案 0 :(得分:17)

Java中的

byte是一个介于-128和127之间的数字(有符号,就像Java中的每个整数一样(char除外)如果要计算它))。通过与0xff进行联系,您强制它在0到255之间为正int

它之所以有效,是因为Java会使用符号扩展执行向int的扩展转换,因此您将使用否定byte而不是负int。使用0xff进行屏蔽只会留下较低的8位,从而使数字再次为正(以及您最初的意图)。

您可能没有注意到差异,因为您使用byte[]进行了测试,其中的值仅小于128.

小例子:

public class A {
    public static void main(String[] args) {
        int[] ip = new int[] {192, 168, 101, 23};
        byte[] ipb = new byte[4];
        for (int i =0; i < 4; i++) {
            ipb[i] = (byte)ip[i];
        }

        for (int i =0; i < 4; i++) {
            System.out.println("Byte: " + ipb[i] + ", And: " + (0xff & ipb[i]));
        }
    }
}

打印

Byte: -64, And: 192
Byte: -88, And: 168
Byte: 101, And: 101
Byte: 23, And: 23

显示byte中的内容之间的差异,当它仍为int时进入字节的内容与&操作的结果之间的差异。

答案 1 :(得分:3)

由于您已在此处使用字节数组,并且您正在执行按位操作,因此可以忽略Java如何将所有字节视为已签名。毕竟,你现在正处理位级别,并且在位级别上没有“有符号”或“无符号”值。

使用全1来掩盖8位值(一个字节)只是浪费周期,因为什么都不会被屏蔽掉。如果被比较的两个位都为真,则双位AND将返回true,因此如果掩码包含全1,则可以保证在AND操作之后掩码值的所有位都保持不变。

请考虑以下示例:

Mask off the upper nibble:
    0110 1010
AND 0000 1111 (0x0F)
  = 0000 1010
Mask off the lower nibble:
    0110 1010
AND 1111 0000 (0xF0)
  = 0110 0000
Mask off... Eh, nothing:
    0110 1010
AND 1111 1111 (0xFF)
  = 0110 1010

当然,如果你在这里使用一个完整的int,你会得到其他人说的结果:你强制“int”相当于一个无符号字节。

答案 2 :(得分:1)

在这个例子中,我看不出它会有什么不同。你是用一个字节和0xff。根据定义,字节具有8位,并且添加屏蔽最后8位。所以你要花8的最后8,这不会做任何事情。

如果你使用它的东西大于一个字节,一个短或一个整数或其他任何东西,那么使用0xff进行安定是有意义的。

答案 3 :(得分:1)

如果有负字节,这应该只会有所不同。 & 0xff通常用于将字节解释为无符号。