Akira's Blog

神奈川在住のITエンジニアの雑記です。主にプログラミング(Perl, Java など)やネットワーク技術についての小ネタを、ちょっとずつ書いていきます。

byte型とint型の変換

以前、Javaのbyte型とint型との変換について勉強するために作成したテストコード。

public class TestByte {

    public static void main(String[] args) {

        // Test1
        byte byteData = (byte) 0xC7;  // 11000111
        // If there is no "(byte)", 0xC7 is looked as int.
        System.out.println(byteData); // -57

        // Test2
        int intData =  0xC7;         // 00000000 00000000 00000000 11000111
        System.out.println(intData); // 199

        // Test3
        int castedData = (int)byteData; // 11111111 11111111 11111111 11000111
        System.out.println(castedData); // -57

        // Test4
        int positiveNumber = byteData & 0xff; // 11111111 11111111 11111111 11000111 & 00000000 00000000 00000000 11111111
        // 0xff is looked as int, so this is "int" & "int".
        // Result: 00000000 00000000 00000000 11000111
        System.out.println(positiveNumber);   // 199
    }
}
  • Test1: 0xC7 は、byte型だと先頭bitが立っているので、Javaにより負数と解釈される。なお、(byte)のキャストがないと、0xC7はint型と扱われ byteData への代入の際にコンパイルエラーとなる。
  • Test2: 0xC7 は、int型だと先頭bitが立っていないので、Javaにより正数と解釈される。
  • Test3: 先頭bitが立っているbyte型のデータをint型にキャストすると、拡張された上位bitが全て 1 で埋められ、Javaにより負数と解釈される。
  • Test4: byte型のデータをintで(暗黙的に)キャストする際、0xff とのANDを取ると、拡張された上位bitは全て 0 で埋められ、Javaにより正数と解釈される。


ソース解析を行っていて、久々に出くわすと、あれ何だっけ・・?と思ってしまうことがあるので、、ここに纏めてみた。

要は、明示的にも暗黙的にも、byte型をint型にキャストする場合、拡張された上位bitが全て 1 で埋まることがあるので、要注意ということ。これは、byte→int に限らず、型を大きい方向に拡張すると起きる。
普通に数値計算する範囲では問題にはならないと思うが、バイト列を16進ダンプ文字列に変換する処理を書くときなどは、知らないとはまると思う。