Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could someone explain to me what the following Java code is doing?

byte s[] = getByteArray()
for(.....)
Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);

I understand that you are trying to convert the byte into hex string. What I don't understand is how that is done. For instance if s[i] was 00000001 (decimal 1) than could you please explain:

  1. Why 0x000000ff & 00000001 ? Why not directly use 00000001?
  2. Why result from #1 | 0xffffff00?
  3. Finally why substring(6) is applied?

Thanks.

like image 904
user_1357 Avatar asked Dec 22 '22 21:12

user_1357


1 Answers

It's basically because bytes are signed in Java. If you promote a byte to an int, it will sign extend, meaning that the byte 0xf2 will become 0xfffffff2. Sign extension is a method to keep the value the same when widening it, by copying the most significant (sign) bit into all the higher-order bits. Both those values above are -14 in two's complement notation. If instead you had widened 0xf2 to 0x000000f2, it would be 242, probably not what you want.

So the & operation is to strip off any of those extended bits, leaving only the least significant 8 bits. However, since you're going to be forcing those bits to 1 in the next step anyway, this step seems a bit of a waste.

The | operation following that will force all those upper bits to be 1 so that you're guaranteed to get an 8-character string from ffffff00 through ffffffff inclusive (since toHexString doesn't give you leading zeroes, it would translate 7 into "7" rather than the "07" that you want).

The substring(6) is then applied so that you only get the last two of those eight hex digits.

It seems a very convoluted way of ensuring you get a two-character hex string to me when you can just use String.format ("%02x", s[i]). However, it's possible that this particular snippet of code may predate Java 5 when String.format was introduced.


If you run the following program:

public class testprog {
    public static void compare (String s1, String s2) {
        if (!s1.equals(s2))
            System.out.println ("Different: " + s1 + " " + s2);
    }
    public static void main(String args[]) {
        byte b = -128;
        while (b < 127) {
            compare (
                Integer.toHexString((0x000000ff & b) | 0xffffff00).substring(6),
                String.format("%02x", b, args));
            b++;
        }
        compare (
            Integer.toHexString((0x000000ff & b) | 0xffffff00).substring(6),
            String.format("%02x", b, args));
        System.out.println ("Done");
    }
}

you'll see that the two expressions are identical - it just spits out Done since the two expressions produce the same result in all cases.

like image 92
paxdiablo Avatar answered Dec 24 '22 09:12

paxdiablo