javabitwise-operatorspackingbit-packing

use of the bitwise operators to pack multiple values in one int


Low level bit manipulation has never been my strong point. I will appreciate some help in understanding the following use case of bitwise operators.Consider...

int age, gender, height, packed_info;

. . .   // Assign values 

// Pack as AAAAAAA G HHHHHHH using shifts and "or"
packed_info = (age << 8) | (gender << 7) | height;

// Unpack with shifts and masking using "and"
height = packed_info & 0x7F;   // This constant is binary ...01111111
gender = (packed_info >> 7) & 1;
age    = (packed_info >> 8);

I am not sure what this code is accomplishing and how? Why use the magic number 0x7F ? How is the packing and unpacking accomplished?

Source


Solution

  • As the comment says, we're going to pack the age, gender and height into 15 bits, of the format:

    AAAAAAAGHHHHHHH
    

    Let's start with this part:

    (age << 8)
    

    To start with, age has this format:

    age           = 00000000AAAAAAA
    

    where each A can be 0 or 1.

    << 8 moves the bits 8 places to the left, and fills in the gaps with zeroes. So you get:

    (age << 8)    = AAAAAAA00000000
    

    Similarly:

    gender        = 00000000000000G
    (gender << 7) = 0000000G0000000
    height        = 00000000HHHHHHH
    

    Now we want to combine these into one variable. The | operator works by looking at each bit, and returning 1 if the bit is 1 in either of the inputs. So:

    0011 | 0101 = 0111
    

    If a bit is 0 in one input, then you get the bit from the other input. Looking at (age << 8), (gender << 7) and height, you'll see that, if a bit is 1 for one of these, it's 0 for the others. So:

    packed_info = (age << 8) | (gender << 7) | height = AAAAAAAGHHHHHHH
    

    Now we want to unpack the bits. Let's start with the height. We want to get the last 7 bits, and ignore the first 8. To do this, we use the & operator, which returns 1 only if both of the input bits are 1. So:

    0011 & 0101 = 0001
    

    So:

    packed_info          = AAAAAAAGHHHHHHH
    0x7F                 = 000000001111111
    (packed_info & 0x7F) = 00000000HHHHHHH = height
    

    To get the age, we can just push everything 8 places to the right, and we're left with 0000000AAAAAAAA. So age = (packed_info >> 8).

    Finally, to get the gender, we push everything 7 places to the right to get rid of the height. We then only care about the last bit:

    packed_info            = AAAAAAAGHHHHHHH
    (packed_info >> 7)     = 0000000AAAAAAAG
    1                      = 000000000000001
    (packed_info >> 7) & 1 = 00000000000000G