darksky
darksky

Reputation: 21019

Unsigned Bytes in Java

Bytes in Java are signed by default. I see on other posts that a workaround to have unsigned bytes is something similar to that: int num = (int) bite & 0xFF

Could someone please explain to me why this works and converts a signed byte to an unsigned byte and then its respective integer? ANDing a byte with 11111111 results in the same byte - right?

Upvotes: 17

Views: 43059

Answers (5)

user2808577
user2808577

Reputation: 121

In Java 8 such method appeared in Byte class:

/**
 * Converts the argument to an {@code int} by an unsigned
 * conversion.  In an unsigned conversion to an {@code int}, the
 * high-order 24 bits of the {@code int} are zero and the
 * low-order 8 bits are equal to the bits of the {@code byte} argument.
 *
 * Consequently, zero and positive {@code byte} values are mapped
 * to a numerically equal {@code int} value and negative {@code
 * byte} values are mapped to an {@code int} value equal to the
 * input plus 2<sup>8</sup>.
 *
 * @param  x the value to convert to an unsigned {@code int}
 * @return the argument converted to {@code int} by an unsigned
 *         conversion
 * @since 1.8
 */
public static int toUnsignedInt(byte x) {
    return ((int) x) & 0xff;
}

Upvotes: 12

Marius Burz
Marius Burz

Reputation: 4645

As you see the result is an int not a byte

How it works, say we have a byte b = -128;, this is represented as 1000 0000, so what happens when you execute your line? Let's use a temp int for this, say:
int i1 = (int)b; i1 is now -128 and this is actually represented in binary like this:

1111 1111 1111 1111 1111 1111 1000 0000

So what does i1 & 0xFF look like in binary?

1111 1111 1111 1111 1111 1111 1000 0000
&
0000 0000 0000 0000 0000 0000 1111 1111

which results in

0000 0000 0000 0000 0000 0000 1000 0000

and this is exactly 128, meaning your signed value converted to unsigned.

Edit
Convertint byte -128 .. 127 into 0 .. 255

int unsignedByte = 128 + yourByte;

You cannot represent the values 128 to 255 by using a byte, you must use something else, like an int or a smallint.

Upvotes: 3

Michael Borgwardt
Michael Borgwardt

Reputation: 346240

ANDing a byte with 11111111 results in the same byte - right?

Except you're ANDing with 00000000000000000000000011111111, because 0xFF is an int literal - there are no byte literals in Java. So what happens is that the byte is promoted to int (the typecast is unnecessary), has its sign extended (i.e. keeps the possibly negative value of the byte, but then the sign extension is reverted by ANDing it with all those zeroes. The result is an int that has as its least significant bits exactly the former byte and thus the value the byte would have had were it unsigned.

Upvotes: 16

700 Software
700 Software

Reputation: 87773

Yes, but this way you can be sure you will never get a number >255 or <0.

If the first bit is 1, the number is negative. If you convert byte to int, if it is negative it will be pre-pended with 1 bytes and if positive, with 0 bytes. Running the and routine will drop all the bytes left of the first 8. This in effect adds 256 to negative bytes.

Upvotes: 0

Ryan Stewart
Ryan Stewart

Reputation: 128749

A typecast has a higher precedence than the & operator. Therefore you're first casting to an int, then ANDing in order to mask out all the high-order bits that are set, including the "sign bit" of the two's complement notation which java uses, leaving you with just the positive value of the original byte. E.g.:

let byte x = 11111111 = -1
then (int) x = 11111111 11111111 11111111 11111111
and x & 0xFF = 00000000 00000000 00000000 11111111 = 255

and you've effectively removed the sign from the original byte.

Upvotes: 27

Related Questions