在 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 == 5
和 shift == 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;
}
我是位操作的新手,但我正在努力将其转换为代码。 对于以下功能,我需要制作一个位掩码
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 == 5
和 shift == 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;
}