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
.
适用于从 1
到 32
的 offset
值的更好替代方案是:
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)))
所以我在尝试通过掩码隔离一定数量的位时遇到了问题。本质上我有一定数量的位我想从单个字节(所以 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
.
适用于从 1
到 32
的 offset
值的更好替代方案是:
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)))