Shifts aren't just a way to do multiplication/division by powers of two. They are one way that you can isolate individual bit sequences in an integer. For example, let's say I have the a 16-bit integer whose value is 65,280 (0xFF00). It's binary representation is like so:
1111 1111 0000 0000
Now what happens if we shift that value right by 1? Yes, we divide the integer by 2, but look at what happens to the binary representation:
0111 1111 1000 0000
We basically shifted the value over by 1 bit. Using shifts in conjunction with AND operations, we can isolate any part of the integer.
Let's say I want to isolate all four hex digits in that 16-bit number. (Bare in mind that every four bits are represented by one hexadecimal digit.) We can do so like this:
a = x >> 12 & 0xF;
b = x >> 8 & 0xF;
c = x >> 4 & 0xF;
d = x & 0xF;
In the end, A's value will be 0xF, B's value will be 0xF, C's value will be 0x0 and D's value will be 0x0. (We've effectively split the 16-bit number into four parts.) Let's review why this works:
A:
For A, we shift the number right by 12 bits:
Code:
1111 1111 0000 0000 -> 0000 0000 0000 1111
Then we AND that value with 0xF. (Note that this step actually isn't required for A, since only the last four bits can be non-zero after a 16-bit integer is shifted right by 12 bits.):
Code:
0000 0000 0000 1111
& 0000 0000 0000 1111
---------------------
0000 0000 0000 1111
So our result for A is 0000 0000 0000 1111 (0x000F).
B:
For B, we shift the number right by 8 bits:
Code:
1111 1111 0000 0000 -> 0000 0000 1111 1111
Then we AND that value with 0xF. (This time this step is required to clear all but the last four bits, since there may have been set bits to the left of our bits of interest.):
Code:
0000 0000 1111 1111
& 0000 0000 0000 1111
---------------------
0000 0000 0000 1111
So our result for B is 0000 0000 0000 1111 (0x000F).
C:
For C, we shift the number right by 4 bits:
Code:
1111 1111 0000 0000 -> 0000 1111 1111 0000
Then we AND that value with 0xF.:
Code:
0000 1111 1111 0000
& 0000 0000 0000 1111
---------------------
0000 0000 0000 0000
So our result for C is 0000 0000 0000 0000 (0x0000).
D:
For D, we needn't shift the value at all, since the integer is already shifted to the bit sequence we want. (This is the equivalent to shifting the integer right by 0.)
So we just AND that value with 0xF.:
Code:
1111 1111 0000 0000
& 0000 0000 0000 1111
---------------------
0000 0000 0000 0000
So our result for D is 0000 0000 0000 0000 (0x0000).
As you can see, we used bit shifts to 'slide' the bits of interest to the end of the integer, then we used AND to trim off the part we didn't want.