Search code examples
javafile-iobit-manipulationoperatorsbit

What does 0xff <<n do in Java?


From a Inputstream , i read the first 4 Bytes and packed these to obtain some information in this case the size/len of the Stream.

For that i use follow code (Example 1) that i copy from another project

Example 1: uses a byte array,where the values are read from InputStream into the array named in_buf[] with lenght 4 and which values are {0,0,12,26}.

Example 1

int size = (((in_buf[0] & 0xff) << 24) | ((in_buf[1] & 0xff) << 16) |
            ((in_buf[2] & 0xff) << 8) | (in_buf[3] & 0xff)); // result its 3098

and as a result i become the value of the size , nice but..

i need to explain what happens here, and i try to split all the function to see better what happens and debug , and i become following results

    int byte1 = ((in_buf[0] & 0xff) << 24); // result 0
    int byte2 = ((in_buf[1] & 0xff) << 16); // result 0
    int byte3 = ((in_buf[2] & 0xff) << 8);  // result 3072
    int byte4 = (in_buf[3] & 0xff);         // result 26

then i deduce that from Example 1 the result of size ist the sume of 0+0+3072+26 but what exacly happens (only with value 12 and 26) here? or which operation it's maked?

Something like this ?

0000 0000 0000 1100  //12  << 8
0000 1100 0000 0000  // result after << 8

And why we need use the mask & 0xff ?

cuz when you debug int byte3a = (in_buf[3] & 0xff) the result ist same that int byte3b = in_buf[3]; so 12, *where value of in_buf[3]=12 ; I add a image from my debug results.

What happens or make this in_buf[3] & 0xff , something like?

  0000 0000 0000 1100 (12)
& 0000 0000 1111 1111 (0xff)
  -------------------
  0000 0000 1111 0011 ?

Screenshot from Eclipse


Solution

  • some thing like these ?

    Yes, except that the operands undergo numeric promotion and turns into an int, so you should technically show 32 bits.

    and why we need use the mask & 0xff?

    This is so we treat negative bytes as positive ints, essentially what toUnsignedInt is doing. It doesn't do anything for non-negative bytes, but for a negative byte, say -1:

    1111 1111
    

    When that gets converted to int due to numeric promotion, it will be sign-extended to 32-bits. That is, the sign will stay negative. Basically this means that if the number is negative, we pad 1s, otherwise we pad 0s. So -1 becomes:

    1111 1111 1111 1111 1111 1111 1111 1111
    

    Now if you use the << 8 on that, it will be:

    1111 1111 1111 1111 1111 1111 0000 0000
    

    which is -256. Now let's see what happens if you do & 0xff before << 8. Numeric promotion happens, and converts your byte to 32 ones just like before, but & 0xff gets only the 8 least significant bits! So the int now becomes:

    0000 0000 0000 0000 0000 0000 1111 1111
    

    This is how you get your original byte, padding with 0s. And then << 8 does the obvious thing:

    0000 0000 0000 0000 1111 1111 0000 0000