How to extract specific bits from a number in C?
There are two building blocks that you need to know to build this yourself:
- Getting
N
least significant bits requires constructing a bit mask withN
ones at the end. You do it like this:((1 << N)-1)
.1 << N
is2 ^ N
: it has a single1
at theN+1
st position, and all zeros after it. Subtracting one gives you the mask that you need. - Dropping
M
least significant bits is a simple shift to the right:k >> M
Now your algorithm for cutting out from M
to N
becomes a two-step process: you shift the original value M
bits to the right, and then perform a bit-wise AND
with the mask of N-M
ones.
#define LAST(k,n) ((k) & ((1<<(n))-1))#define MID(k,m,n) LAST((k)>>(m),((n)-(m)))int main() { int a = 0xdeadbeef; printf("%x\n", MID(a,4,16)); return 0;}
This fragment cuts out bits from 4, inclusive, to 16, exclusive, and prints bee
when you run it. Bits are numbered from zero.
unsigned short extract(unsigned short value, int begin, int end){ unsigned short mask = (1 << (end - begin)) - 1; return (value >> begin) & mask;}
Note that [begin, end)
is a half open interval.
It can be done like this:
mask = ~(~0 << (end - start + 1));value = (n >> start) & mask;
where n
is the original integer and value
is the extracted bits.
The mask
is constructed like this:
1. ~0 = 1111 1111 1111 1111 1111 1111 1111 11112. ~0 << (end - start + 1) = 1111 1111 1111 1111 1100 0000 0000 0000 // assuming we are extracting 14 bits, the +1 is added for inclusive selection // ensure that end >= start3. ~(~0 << (end - start + 1)) = 0000 0000 0000 0000 0011 1111 1111 1111
Now n
is shifted right by start
bits to align the desired bits to the left.Then a bitwise AND gives the result.