445 words
2 min

JavaのByteの計算で詰まった話

2024-06-04

この記事は公開日から2年以上が経過しています。

入力されたbyteが0x00 ~ 0xFDの間にあるか確認したい#

指定されたbyteが0x00 ~ 0xFDにいる事を確認したく以下コードを書いたとき

Main.java
byte arg = (byte) 0x01;

if((byte) 0x00 >= arg && arg =< (byte) 0xFD){
  System.out.println("問題なし");
}

何故か条件に入らない、、、

Javaのbyteは符号付き#

Javaのbyteは符号付きのためbyteを数値として表すと
-128 ~ 127
になる。
つまり、2進数の1000 0000で符号付きとして判断されるため
0x80 ~ 0xFFまではマイナスの値になる。

なので

(byte) 0x00 > (byte) 0xFF

trueになる。

どうしたか#

intとして扱ってあげれば符号付きで変換されないので

Main.java
byte arg = (byte) 0x01;

if(0x00 >= arg && arg =< 0xFD){
  System.out.println("問題なし");
}

としてあげれば、やりたいことができる。


byte触る機会少なかったら気づかなかった…(言い訳)

補足:ビットマスク演算 (arg & 0xFF) を使った無符号化処理#

また、別の解決策として & 0xFF によるビット演算を行い、int 型にプロモーションする方法も一般的です。

Main.java
byte arg = (byte) 0xFD; // 数値としては -3
int unsignedArg = arg & 0xFF; // 0x000000FD (数値としては 253)

if (unsignedArg >= 0x00 && unsignedArg <= 0xFD) {
    System.out.println("0x00〜0xFDの範囲内です");
}

arg & 0xFF を行うことで、符号拡張によって1で埋まった上位24ビットがゼロクリアされ、0〜255の無符号整数(unsigned byteと同等)として安全に比較・計算が行えるようになります。
パケット解析やバイナリプロトコルを扱う処理では定番の書き方なので、あわせて押さえておくと安心です。

JavaのByteの計算で詰まった話
https://tech.storias-blog.com/blogs/stuck_on_java_byte_math/
作者
Storia
公開日
2024-06-04