1. ホーム
  2. java

[解決済み] Javaがintをbyteに変換するときの奇妙な動作?

2022-06-26 10:52:16

質問

int i =132;

byte b =(byte)i; System.out.println(b);

呆気ない。なぜ出力が -124 ?

どのように解決するのですか?

Javaでは int は32ビットです。A byte は8 bits .

Javaではほとんどのプリミティブ型が符号付きであり byte , short , int そして long は2の補数で符号化されます。 (その char 型は符号なしであり、符号の概念は boolean .)

この数値スキームでは、最上位ビットが数値の符号を指定します。より多くのビットが必要な場合、最上位ビット ("MSB") は単に新しい MSB にコピーされます。

ですから、もしあなたがバイト 255 : 11111111 と表現したい場合、それを int (32ビット)として表現したい場合は、単純に1を24回左にコピーします。

さて、負の 2 の補数を読む 1 つの方法は、最下位ビットから始めて、最初の 1 を見つけるまで左に移動し、その後のすべてのビットを反転させることです。その結果得られる数値は、その数値の正バージョンとなります。

たとえば 11111111 になります。 00000001 = -1 . これがJavaが値として表示するものです。

おそらくあなたがしたいことは、バイトの符号なし値を知ることです。

最下位の8ビット以外を削除するビットマスクでこれを達成することができます。(0xff)

というわけで。

byte signedByte = -1;
int unsignedByte = signedByte & (0xff);

System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);

印刷されるでしょう。 "Signed: -1 Unsigned: 255"

ここでは実際に何が起こっているのでしょうか?

余計な符号ビット(最下位8ビットの左側にある1)をすべてマスクするためにビット単位のANDを使用しています。 int がバイトに変換されるとき、Java は左から 24 ビットを切り落とします。

1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101

32ビット目が8ビット目ではなく符号ビットになっているため(そして符号ビットを正の値である0に設定している)、バイトの元の8ビットがJavaによって正の値として読み取られます。