3

私はJavaに取り組んでいます。なぜJavaがこの出力を生成するのか疑問に思っています。ここでコードを共有しています。

public class vvn {

    public static void main(String[] args)
    {
        byte [] arr = new byte[4];
        arr[0] = (byte)157;
        arr[1] = 1;
        arr[2] = 0;
        arr[3] = 0;
        System.out.format("read 0x%x 0x%x 0x%x 0x%x \n",arr[3],arr[2],arr[1],arr[0]);
        int v = (arr[0] | (arr[1] << 8) | (arr[2] << 16) | (arr[3] << 24));
        System.out.format("read 0x%x\n",v);

    }

}

そして、私は出力を得ました

read 0x0 0x0 0x1 0x9d 
read 0xffffff9d

出力は 0x0000019d になるはずだと思っていました

4

5 に答える 5

5

バイト (符号付き 8 ビット) から整数 (符号付き 32 ビット) に変換しています。最上位ビット (一番左のビット) は符号を保持します ( 2 の補数を参照)。

あなた15710011101バイナリです。この値を符号付きバイトに割り当てるため( Java には符号なしバイトはありません)、これは実際には負の数です-99

これで、byte から int に変換すると、値が保持されます。負の数の場合、これは符号を維持するためにすべてのビットを左に設定することを意味します。あなたの場合、 に10011101なり11111111 11111111 11111111 10011101ます。

とにかく、Java で符号なしバイトを扱うのは悪夢です。基本的に、次のようにすべてを 0xff でマスクする必要があります (「左側のもの」をカットするため):

int v = ((arr[0] & 0xff) |
    ((arr[1] & 0xff) << 8) |
    ((arr[2] & 0xff) << 16) |
    ((arr[3] & 0xff) << 24));

美しいですね。

更新 1:また、Guava のUnsignedBytesに興味があるかもしれません...

更新 2: Java 8 Byte には toUnsignedInt() および toUnsignedLong() メソッドがあります。したがって、計算は次のようになります。

int v = (Byte.toUnsignedInt(arr[0]) |
    (Byte.toUnsignedInt(arr[1]) << 8) |
    (Byte.toUnsignedInt(arr[2]) << 16) |
    (Byte.toUnsignedInt(arr[3]) << 24));
于 2016-02-24T09:07:02.143 に答える