在 C 中制作位掩码

Making bitmasks in C

我是位操作的新手,但我正在努力将其转换为代码。 对于以下功能,我需要制作一个位掩码

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

位掩码函数应该有宽度和位移。如果 w=5 和 s=1 它应该给出 00111110.

我应该如何处理这个问题?这是我一直在尝试的最新代码:

*mask |= width << shift;

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

单元测试:

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

十进制值5是二进制00000101。将它向左移动一位可以得到 00001010.

如果你想让5变成00011111(十进制31)那么最简单的解决办法就是找出值00100000(十进制32)和减一。

请记住,我们正在处理 2 的幂,如果将 2 乘以 5 的幂,我们将得到 32,然后可以减去 1 以获得基础掩码。但不是使用 pow 函数或在循环中乘法,我们可以将值 1 左移五步 (1 << 5).

综合起来,你应该将 1 左移 width 位,减去 1,然后将结果左移 shift 位:

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

使用 width == 5shift == 1 则以上将为您提供二进制 00111110(十进制 62)。

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;
}