Search code examples
cbitmask

Making bitmasks in C


I'm new to bit manipulation but I'm struggling to translate it to code. For the following function I need to make a bitmask

void make_bitmask(unsigned int width, unsigned int shift,unsigned int* mask)

The bitmask function is supposed to have a width and a shift. if w=5 and s=1 it should give 00111110.

How should I approach this? This is my latest code I've been trying:

*mask |= width << shift;

Changed to *mask = ((1 << width) - 1) << shift;

Unit test:

static void test_make_bitmask_correct_width(void)
{
 unsigned int mask = 0;
make_bitmask(1,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0x1, mask);
make_bitmask(2,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0x3, mask);
make_bitmask(5,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0x1f, mask);
make_bitmask(32,0,&mask)
TEST_ASSERT_EQUAL_HEX32(0xffffffff, mask); // the one that is currently failing  mask is 0x000000000

Solution

  • void make_bitmask(unsigned int width, unsigned int shift,unsigned int *mask)
    {
        /*  With unlimited arithmetic, (1 << width) - 1 would give us a mask of
            width bits, starting at the low bit position.  E.g., with width 3, 1 <<
            3 would give binary 1000, and subtracting one would give 111, a mask of
            3 bits.  However, in C arithmetic, if width is the full width of an
            unsigned int, then "1u << width" would overflow.  To avoid this, if
            width is positive, we shift 2u by width-1.  If width is zero, we simply
            use the hardcoded result for a mask of zero bits, zero.
        */
        unsigned int t = width ? (2u << width-1) - 1u : 0u;
    
        //  Shift the mask to the desired position and store it.
        *mask = t << shift;
    }