【问题标题】:Bitwise AND, Bitwise Inclusive OR question, in JavaJava 中的按位与,按位包含或问题
【发布时间】:2009-02-18 12:59:31
【问题描述】:

我在一个项目中有几行代码,我看不到...的价值

buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);

它从文件中读取文件缓冲区,存储为字节,然后传输到缓冲区[i],如图所示,但我不明白整体目的是什么,有什么想法吗?

谢谢

【问题讨论】:

    标签: java bit-manipulation byte operator-keyword


    【解决方案1】:

    正如其他答案已经说明的那样,(currentByte & 0x7F) | (currentByte & 0x80) 等同于(currentByte & 0xFF)。 JLS3 15.22.1 说这被提升为int

    当一个运算符 & 的两个操作数, ^, 或 |是一种类型 可转换(第 5.1.8 节)为原语 整数类型,二进制数值 促销首先在 操作数(§5.6.2)。的类型 位运算符表达式是 操作数的提升类型。

    因为 JLS3 5.6.2 表示当 currentByte 具有类型 byte 并且 0x7Fint 时(就是这种情况),那么两个操作数都被提升为 int

    因此,buffer 将是元素类型为 int 或更宽的数组。

    现在,通过在int 上执行& 0xFF,我们有效地将原始byte 范围-128..127 映射到无符号范围0..255,例如java.io 流经常使用的操作.

    您可以在下面的代码 sn-p 中看到这一点。请注意,要了解这里发生了什么,您必须知道 Java 将整数类型(char 除外)存储为 2's complement 值。

    byte b = -123;
    int r = b;
    System.out.println(r + "= " + Integer.toBinaryString(r));
    int r2 = b & 0xFF;
    System.out.println(r2 + "= " + Integer.toBinaryString(r2));
    

    最后,对于一个真实的示例,查看 Javadoc 和 java.io.ByteArrayInputStreamread 方法的实现:

    /**
     * Reads the next byte of data from this input stream. The value 
     * byte is returned as an <code>int</code> in the range 
     * <code>0</code> to <code>255</code>. If no byte is available 
     * because the end of the stream has been reached, the value 
     * <code>-1</code> is returned. 
     */
    public synchronized int read() {
    return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }
    

    【讨论】:

      【解决方案2】:
       (currentByte & 0x7F) | (currentByte & 0x80)
      

      等价于

       currentByte & (0x7F | 0x80)
      

      等于

       currentByte & 0xFF
      

      完全一样
       currentByte
      

      编辑:我只看了右边的作业,我仍然认为等价是正确的。

      但是,代码似乎希望将带符号的字节转换为更大的类型,同时将字节解释为无符号。

      有没有更简单的方法可以在 java 中将有符号字节转换为无符号字节?

      【讨论】:

      • 最后一步是错误的,因为负字节会被符号扩展为负整数,而 currentByte & 0xFF 是正数。
      • 代码中没有任何内容表明缓冲区是一个比字节宽的数组。
      • @Welbog 代码中没有任何内容表明缓冲区是一个字节数组。
      • 缓冲区的元素类型为 int 或更宽,否则无法编译。
      • 另外,Java 中不存在无符号字节。
      【解决方案3】:

      我认为有人在这里想太多了。那是不对的。

      我只有一句话

      • 原作者担心运行时将字节替换为本机有符号整数(可能是 32 位),并明确试图告诉我们有关符号位“特殊”的一些信息?

      这是遗留下来的代码。除非你知道你在一个可疑的运行时间?无论如何,“缓冲区”的类型是什么?

      【讨论】:

      • 两者都是数组 os 字节我尝试了 Timbo 的建议,并且在更改时它的 fubared :-/
      • 缓冲区是 int 或更宽的元素类型,否则它不应该编译。
      • @Dave 很奇怪,什么症状?
      • 好吧,它是视频编解码器的一部分,这是文件输入管理器,在不同的点上,我最终(几乎瞬间)遇到空指针异常和数组越界...... :(
      • 我们需要看更多的代码,所有的变量都是从哪里来的? 'buffer' 或 'filebuffer' 可能为 null 并且 currentPosition 可能超出范围...需要...更多...源...
      【解决方案4】:

      复杂的按位逻辑完全是多余的。

      for (int i = 0; i < buffer.length; i++) {
          buffer[i] = filebuffer[currentPosition + i] & 0xff;
      }
      

      做同样的事情。如果缓冲区被声明为一个字节数组,你甚至可以省略 & 0xff,但不幸的是声明没有显示。

      原因可能是最初的开发者对用 Java 签名的字节感到困惑。

      【讨论】:

      • 缓冲区永远不能是带有 &0xFF 的 byte[] 类型。没有它,你会改变结果。
      【解决方案5】:

      按位与运算的结果在两个位均为 1 的位上为 1,而按位或运算的结果在机器人位之一为 1 的位上具有一个。

      因此,值 0x65 的示例评估:

        01100101 0x65
      & 01111111 0x7F
      ===============
        01100101 0x65
      
        01100101 0x65
      & 10000000 0x80
      ===============
        00000000 0x00
      
        01100101 0x65
      | 00000000 0x00
      ===============
        01100101 0x65
      

      【讨论】:

      • 你的 |底部的步骤是错误的。 x的结果| 0 表示所有 x 都是 x。
      • 我在该行下方得到 01100101 0x65(最后一个操作是 |,而不是 &)
      【解决方案6】:

      这类逻辑运算的好处是:您可以尝试所有可能的组合(全部 256 种)并验证您是否得到了预期的答案。

      【讨论】:

        【解决方案7】:

        原来,正在读取字节的文件是有符号位表示法,并且长度不同,因此需要执行此任务以允许将其扩展为 java int 类型,同时保留它的正确符号:)

        【讨论】:

          猜你喜欢
          • 2013-05-14
          • 2020-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-13
          • 1970-01-01
          • 1970-01-01
          • 2018-04-03
          相关资源
          最近更新 更多