Bit shifts and their logical operators

This program below moves the last (least significant) and penultimate byte variable i of type int. I am trying to understand why a programmer wrote this

i = (i & LEADING_TWO_BYTES_MASK) | ((i & PENULTIMATE_BYTE_MASK) >> 8) | ((i & LAST_BYTE_MASK) << 8);

      

Can anyone explain to me in plain english what is going on in the program below.

#include <stdio.h>
#include <cstdlib>

#define LAST_BYTE_MASK 255 //11111111
#define PENULTIMATE_BYTE_MASK 65280 //1111111100000000
#define LEADING_TWO_BYTES_MASK 4294901760 //11111111111111110000000000000000


int main(){
    unsigned int i = 0;
    printf("i = ");
    scanf("%d", &i);
    i = (i & LEADING_TWO_BYTES_MASK) | ((i & PENULTIMATE_BYTE_MASK) >> 8) | ((i & LAST_BYTE_MASK) << 8);
    printf("i = %d", i);
    system("pause");
}

      

+3


source to share


3 answers


The expression is really a bit confusing, but essentially the author does this:

// Mask out relevant bytes
unsigned higher_order_bytes = i & LEADING_TWO_BYTES_MASK;
unsigned first_byte = i & LAST_BYTE_MASK;
unsigned second_byte = i & PENULTIMATE_BYTE_MASK;

// Switch positions:
unsigned first_to_second = first_byte << 8;
unsigned second_to_first = second_byte >> 8;

// Concatenate back together:
unsigned result = higher_order_bytes | first_to_second | second_to_first;

      

By the way, defining masks using hexadecimal notation is more readable than using a decimal number. Also, the usage #define

is wrong here. Both C and C ++ have const

:



unsigned const LEADING_TWO_BYTES_MASK = 0xFFFF0000;
unsigned const PENULTIMATE_BYTE_MASK = 0xFF00;
unsigned const LAST_BYTE_MASK = 0xFF;

      

To understand this code, you need to know that &

, |

and bit shifts are done at the bit level .

+6


source


Since you asked for plain English: it swaps the first and second bytes of an integer.



+8


source


It is more instructive to define your masks in hexadecimal rather than decimal, because then they correspond directly to binary representations and it is easy to see which bits are on and off:

#define LAST 0xFF          // all bits in the first byte are 1
#define PEN 0xFF00         // all bits in the second byte are 1
#define LEAD 0xFFFF0000    // all bits in the third and fourth bytes are 1 

      

Then

i = (i & LEAD)             // leave the first 2 bytes of the 32-bit integer the same
    | ((i & PEN) >> 8)     // take the 3rd byte and shift it 8 bits right
    | ((i & LAST) << 8)    // take the 4th byte and shift it 8 bits left 
    );

      

Thus, the expression replaces the two least significant bytes, leaving the two most significant bytes the same.

+3


source







All Articles