有符号字节奇怪行为的位移

时间:2013-03-14 10:05:21

标签: java byte bit-manipulation

我写了一个函数来打印一个字节的位。这通过将最高有效位设置为1来进行,将其与输入字节进行比较,如果它也是1,则打印“1”,否则为“0”。然后比较字节右移。

如何从10000000开始并转换到01000000然后转到00100000 ...

我认为我的问题是由推广到int然后重铸引起的,但我没有看到解决方案。

package errorreporting;

public class ErrorReporting {

ErrorReporting() {
}

public static void main(String[] args) {

    ErrorReporting myError = new ErrorReporting();
    byte myByte = 16;
    myError.printByteArray(myByte);

}

public void printByteArray(byte inputByte) {
    // print out 1 or 0
    byte comparison = -128;
    for (int x = 0; x < 8; x++) {
        if ((inputByte & comparison) != 0) {
            System.out.print("1");
        } else {
            System.out.print("0");
        }
        //       System.out.print(" comparison : " + comparison);
        comparison = (byte) (comparison >>> 1);

    }
    System.out.println(" : " + inputByte);
}

}

这篇文章有一些信息:Java bitshift strangeness

1 个答案:

答案 0 :(得分:1)

  

我相信我的问题是由促销到int然后重铸

引起的

是的,它是一些隐式和显式转换和符号扩展的组合:

  1. 所有参数在转换操作发生之前首先提升为int,另请参阅https://stackoverflow.com/a/3948303/1611055

  2. 由于1,您的无符号移位运算符>>>没有帮助 - 它正确地将0移动到最左侧位置,但由于源参数-128已经在应用班次之前提升为int (产生0xffffff80),在第一班后你最终得到0x7fffffc0

  3. 最简单的解决方案是使用int作为面具:

    int comparison = 0x80;  // -128;
    

    理论上,您仍然可以使用一个字节作为掩码,但是在应用之前,您需要在同时丢弃符号位的同时将其显式转换为int移位运算符,如下所示:

    byte comparison = -128;
    ...
    comparison = (byte)( (((int) comparison) & 0xff) >>> 1);
    

    ((int) comparison) & 0xff)假定该字节应该是“无符号”并将其转换为相应的“unsigned”int值。然后,您可以应用移位运算符(>>>>>并不重要,因为我们在任何情况下都有正int值)并将其强制转换为byte