【问题标题】:Anding with 0xff, clarification neededAnding 与 0xff,需要澄清
【发布时间】:2012-03-30 20:15:31
【问题描述】:

在下面的 sn-p 中,考虑将第 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 不会改变任何内容。是否有理由应用此掩码?

【问题讨论】:

  • 我不确定,但看起来像转换为无符号字节。

标签: java bit-manipulation


【解决方案1】:

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

之所以有效,是因为 Java 将使用符号扩展执行到 int 的扩大转换,因此您将得到一个负数 int,而不是负数 byte。使用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 时进入字节的内容以及&amp; 操作的结果之间的区别。

【讨论】:

  • 回复:“这是因为 0xff 的类型为 int,因此字节也被提升为 int”:到 int 的类型提升实际上会发生,即使两个参数的类型都是byte;对于byte,Java 没有独特的&amp; 运算符。 (在没有&amp; 的版本中,int 的类型提升将在重载解析期间发生,因为StringBuffer 没有append(byte) 方法。)
  • 确实,你是对的。相关部分显然是我们在任何情况下都将符号扩展扩大到int,并且通过屏蔽低 8 位,我们可以再次将其强制为无符号字节:)
  • “无符号,就像 Java 中的每个整数一样” - 你的意思是有符号吗?
  • @NabinBhandari:当然,谢谢。您也可以进行编辑。
【解决方案2】:

由于您已经在此处处理字节数组,并且正在执行按位运算,因此您可以忽略 Java 如何将所有字节视为有符号的。毕竟,您现在是在位级别上工作,并且在位级别上没有“有符号”或“无符号”值之类的东西。

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

考虑以下示例:

屏蔽掉上半字节:
    0110 1010
与 0000 1111 (0x0F)
  = 0000 1010
屏蔽下半字节:
    0110 1010
与 1111 0000 (0xF0)
  = 0110 0000
戴上面具……呃,没什么:
    0110 1010
与 1111 1111 (0xFF)
  = 0110 1010

当然,如果您在这里使用完整的 int,您会得到其他人所说的结果:您将“强制” int 等同于无符号字节。

【讨论】:

    【解决方案3】:

    在这个例子中,我看不出它会有什么不同。您正在使用一个字节来处理 0xff。根据定义,一个字节有 8 位,并且 add 屏蔽了最后 8 位。所以你拿了 8 个中的最后 8 个,这不会有任何作用。

    如果你用 0xff 与它的东西大于一个字节、一个短或一个 int 或其他任何东西,那么用 0xff 与它是有意义的。

    【讨论】:

    • 哎呀,我承认,我误读了这个问题。我在想它是把它放回一个字节数组中,我没有发现它正在将它转换为文本。
    【解决方案4】:

    这只有在有负字节时才会有所不同。 &amp; 0xff 通常用于将字节解释为无符号。

    【讨论】:

      猜你喜欢
      • 2011-11-09
      • 2012-07-18
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2012-06-02
      • 2017-01-18
      • 2016-06-30
      • 1970-01-01
      相关资源
      最近更新 更多