Since bytes are signed in java, in order to obtain unsigned integer values we mask with 0xFF asper:
byte signed = -1;// -—> 0b11111111
int unsigned = signed & 0xFF;// —-> 0b11111111 & 0b11111111
System.out.println(“unsigned: ”+unsigned);//prints 255 instead of -1 since we masked earlier
But when the unsigned int
is casted to a byte it seems nothing happens to it really i.e.
byte resigned = (byte) unsigned;
System.out.println(“resigned: ”+resigned);//same value as earlier signed = -1
Taking a closer look at the initial operation
int unsigned = signed & 0xFF;// the result of 0b11111111 & 0b11111111 is actually = 0b11111111
Even if the value of signed were something else say we had
byte signed = -44;// -—> 0b11010100
int unsigned = signed & 0xFF;// the result of 0b11010100 & 0b11111111 is still actually = 0b11010100
byte resigned = (byte) unsigned;
System.out.println(“resigned: ”+resigned);//same value as signed = -44
So it seems nothing really happens to the actual signed value for the unsigned int
to be possible.
Does masking actually do anything to the (byte) value of an integer or it’s just a way to flag how javac
should treat the integer?
byte signed = -1;// -—> 0b11111111
Correct.
int unsigned = signed & 0xFF;// —-> 0b11111111 & 0b11111111
This is not correct. There are 3 steps.
The value of signed
is converted (sign-extended) to an int
; i.e. 0b11111111
becomes 0b11111111111111111111111111111111
(= 0xFFFFFFFF)
The 0b11111111111111111111111111111111
(= 0xFFFFFFFF
) is ANDed with 0b00000000000000000000000011111111
(= 0x000000FF
) to give 0b00000000000000000000000011111111
(= 0x000000FF
)`
0b00000000000000000000000011111111
(= 0x000000FF
) is assigned to unsigned
.
(Note: it is important to write this out in full so that you understand what happens.)
byte resigned = (byte) unsigned;
There are two steps here too.
The cast (byte)
converts 0b00000000000000000000000011111111
(= 0x000000FF
)
to 0b11111111
(= 0xFF
) i.e. it converts the int
to a byte
.
Then the byte 0b11111111
(= 0xFF
) is assigned to resigned
.
So it seems nothing really happens to the actual signed value for the unsigned int to be possible.
But something did happen! The &
operator started with the sign-extended value 0b11111111111111111111111111111111
(which represents -1) and converted it to 0b00000000000000000000000011111111
(which represents 255).
And you can verify that something happened by running this:
byte signed = -1; // -—> 0b11111111
int x = signed;
System.out.println("x: " + x); // prints -1
The fact that you ended up with the same value as you started with doesn't mean that nothing happened. Something did happen. You converted the byte
value -1
to the int
value 255
, and then you converted it back to the byte -1
.
You can also verify this by reading the relevant sections of the Java Language Specification. (Let me know if you need the references.)
Does masking actually do anything to the (byte) value of an integer or it’s just a way to flag how javac should treat the integer?
Masking really did something.
If you were to look at the bytecodes produced by the javac
compiler you would see codes to do the byte
to int
conversion, the masking and the assignment. Then in the other direction, you would see a bytecode to do an int
to byte
conversion.
However, that is an implementation detail.