bitwise-ANDing with 0xff is important?

匿名 (未验证) 提交于 2019-12-03 01:10:02

问题:

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?

回答1:

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.



回答2:

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


回答3:

(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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!