After reading all of the questions and answers on bit shifting/masking, I simply cannot wrap my head around it. I'm just not understanding how it works on a fundamental level. I've been able to achieve various techniques by using BitArray and BitConverter instead, but I really would like to understand bit shifting/masking better.
The specific need I have is to do the following:
I have a ushort: 0x810E (33038)
Using bit shifting/masking, I'd like to know how to:
- Get the 16th bit Result: 1
- Get the 15th bit Result: 0
- Get a range of bits to create a new ushort value, specifically the first 14 bits Result: 270
As I said, I'm able to perform these tasks using BitArray which is how I've gotten the correct results, but I'd like to understand how to perform these operations using bit shifting/masking.
Any help would be appreciated.
Masking single bits
As you probably know,
ushortis a 16-bit value, so your given number0x810Ecan also be written asBecause there is no shifting operator for
ushort, the value is first converted toint.So, if you want to get the 15th bit, you can take a single bit
and shift it 14 times to the left (right side is filled with
0)and you have created a bitmask.
Now if you combine mask and value with an bitwise
and, you'll get only the value of the 15th bit:which is
0again. To access this bit, you'll have to shift the whole result back to the right 14 times and cast it to aushort.This can be expressed with the following code:
Can we do better?
Although this approach seems to be correct, but there is a simpler way to do this: shift the original value to the right 14 times (result is
00000000 00000000 00000000 00000010, left side is filled with0) and perform a simple bitwise&with1:This results in
C#in:So you avoid one additional shift and we get the same results even when using signed numbers (because there the highest bit, used for the sign, is left unchanged by shifting).
Masking a bit range
To mask a bit range, all you have to do is to change your mask. So, to get the value of the lower 14 bits you can use the mask
In
C#this can be expressed withwhere (
0xFFFFis00000000 00000000 11111111 11111111).