bitwise-ANDing with 0xff is important?
Asked Answered
A

3

22

Doesn't bitwise-ANDing with 0xff essentially mean getting the same value back, for that matter, in this code?

byte[] packet = reader.readPacket();
short sh;
sh = packet[1];
sh &= 0xFF;
System.out.print(sh+" ");

Weirdly, I get a -1 if that ANDing is not included but a 255 when included Could someone explain the reason?

As I see it 0xff is just 1111 1111. Isn't it?

Aggrieved answered 27/9, 2013 at 23:23 Comment(0)
J
34

Yes, 0xff is just 1111 1111. But this is attempting to display the unsigned byte value, even though in Java bytes are signed. The value 0xff is -1 for a signed byte, but it's 255 in a short.

When a byte value of 0xff is read, printing the value would yield -1. So it's assigned to a short which has a bigger range and can store byte values that would normally overflow to be a negative number as a byte as a positive integer, e.g. 144 as a byte is 0x90, or -112, but it can be properly stored as 144 as a short.

So the byte value of -1 is assigned to a short. But what does that do? A primitive widening conversion takes place, and negative values are sign-extended. So 1111 1111 becomes 11111111 11111111, still -1, but this time as a short.

Then the bitmask 0xff (00000000 11111111) is used to get the last 8 bits out again:

  -1: 11111111 1111111
0xFF: 00000000 1111111
======================
 255: 00000000 1111111

It's just a way to get the unsigned byte value, by converting it to short and then masking out the original bits from the byte, to display it as an unsigned value.

Jaye answered 27/9, 2013 at 23:30 Comment(2)
I would give you an upvote, but you'll have to wait 24 minutes for an upvote from me. I am currently out of votes.Chops
"So the byte value of -1 is assigned to a short. But what does that do? A primitive widening conversion takes place, and negative values are sign-extended." -- Excellent info. "Then the bitmask 0xff (00000000 11111111) is used to get the last 8 bits out again" -- huhh.. this is it.. Great thanks man...Aggrieved
L
3

A byte has the range of -128 to 127. This means some values are negative. This is all the values where the top bit is set. So (byte) 0xFF is -1. When you use sign extension to make it a signed short, it becomes (short) 0xFFFF which is -1 as a short. When you mask it, it chop off the extended bits and you treat the byte as if it where unsigned.


You don't get -1 unless your code is different to what you have in the question.

for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) {
    short s = b;
    s &= 0xff;
    System.out.println(b + " & 0xFF = " + s);
}

prints

-128 & 0xFF = 128
-127 & 0xFF = 129
....
-2 & 0xFF = 254
-1 & 0xFF = 255
0 & 0xFF = 0
1 & 0xFF = 1
...
125 & 0xFF = 125
126 & 0xFF = 126
Laural answered 27/9, 2013 at 23:31 Comment(3)
In the question he does say "Weirdly, I get a -1 if that ANDing is not included". It seems to me like he knows WHAT happens but wants to know WHY.Chops
@SimonAndréForsberg Good point. That is what I expected not weird at all.Laural
@SimonAndréForsberg Thanks for having my back... You go me right.. I wanted to know WHY..Aggrieved
F
1

(Assuming two's complement everywhere) Two things:

  1. Bytes are signed, so 0xff in a byte is equal to -1.
  2. When going from a smaller data type to a larger data type (in this case, from a byte to a short), the value is kept. So, sh = packet[1] would set sh to -1, which is 0xffff.

The thing with point #2 is that the "extra" bits get padded with 1s to keep the value whenever the original value is negative. The idea behind ANDing with 0xff is that sh now contains 0x00ff, with those "extra" 1s now removed.

Figuration answered 27/9, 2013 at 23:30 Comment(1)
"the value is kept. ".. that explains.. Thank you very much!Aggrieved

© 2022 - 2024 — McMap. All rights reserved.