C 中的按位运算和掩码

Bitwise operations and masking in C

所以我在尝试通过掩码隔离一定数量的位时遇到了问题。本质上我有一定数量的位我想从单个字节(所以 8 位)中屏蔽(我们称之为偏移量)。有 2 种口罩我需要帮助:

第一个:假设偏移量 = 4,我有一个二进制字节 1110 0001。我想屏蔽大小偏移量的 last 位,这样我就可以得到一个最终的1110 0000 字节(因此屏蔽最后 4 位)。

第二个:假设偏移量为 3,我有一个字节为二进制 1011 0010。我现在想屏蔽 first 几位大小偏移量,以便我有一个0001 0010 的最后一个字节。

我已经粘贴了到目前为止的代码。目前它不适用于我要创建的第一个掩码,因为它掩码了前几位而不是最后一位。我不确定我是否正确创建了面具。

uint8_t mask = (1 << offset) - 1;
byte = (byte & mask);

为了屏蔽低 offset 位,您对 mask 的计算是正确的,但表达式不是。应该是:

byte = (byte & ~mask);

或者简单地说:

byte &= ~mask;

要根据 (1 << offset) - 1 的偏移量计算掩码,您应该注意偏移量必须小于 1 类型中的位数。 1 是一个 int,如果表示 offset < 32,那么您不能以这种方式计算 32 位字段的掩码。

此外,即使31也会出现问题,因为(1 << 31)超出了类型int的范围。为了避免这种情况,你应该写 (1U << offset) - 1 并且你必须先测试是否 offset < 32.

适用于从 132offset 值的更好替代方案是:

unsigned mask = ~0U >> (sizeof(unsigned) * CHAR_BIT - offset);
bits &= ~mask;

或使用相反的掩码更简单:

bits &= ~0U << offset;

这里是获取、清除和设置 unsigned int 中位域的宏:

#define GET_MASK(width)               (~0U >> (sizeof(unsigned) * CHAR_BIT - (width)))
#define GET_FIELD(x, pos, width)      (((x) >> (pos)) & GET_MASK(x, width))
#define CLEAR_FIELD(x, pos, width)    (((x) &= ~(GET_MASK(x, width) << (pos)))
#define SET_FIELD(x, pos, width, val) ((x) = ((x) & ~(GET_MASK(x, width) << (pos))) | ((val) << (pos)))