The function is supposed to extract a bitfield of width n at position p.
There are problems in this function:
p + 1 - n seems bogus but it is the number of bits to the right of the bitfield if p is the bit number of the most significant bit in the bitfield, numbered from 0 for the least significant bit..
the code has implementation defined behavior if the most significant bit of x is included in the bitfield because 0 is a signed integer. 0U should be used instead.
the code does not work to extract a bitfield that has the full width of unsigned int, because shifting by a number of bits greater or equal to the width of the type has undefined behavior. The shift should be split in 2 parts, n - 1 bits and an additional 1 bit. n - 1 will be in the range [0..31] so the variable shift is fully defined.
Here is a more portable version:
// extract `n` bits at position `p`. n in [1..32], p in `[1..32]`
unsigned getbits(unsigned x, int p, int n) {
return (x >> (p + 1 - n)) & ~(~0U << (n - 1) << 1);
}
Here are the steps:
0U is the unsigned int null constant.
~0U has all its value bits set.
~0 << (n - 1) has all its value bits set except for the n - 1 low order bits, which are cleared.
~0 << (n - 1) << 1 has all its value bits set except for the n low order bits, which are cleared.
~(~0 << (n - 1) << 1) has the n low order bits set.
p + 1 - n is the number of bits with lower order than the bitfield
x >> (p + 1 - n) shifts the value to the right, leaving the bitfield in the low order bit positions.
(x >> (p + 1 - n)) & ~(~0 << (n - 1) << 1) masks the higher order bits, leaving just the bitfield value.
Note that there are other ways to compute the mask:
~0U >> (sizeof(unsigned) * CHAR_BIT - n)
(1U << (n - 1) << 1) - 1