因此,我在试图通过掩码隔离一定数量的比特时遇到了麻烦。本质上,我有一定数量的比特,我想屏蔽(让我们称之为偏移)从一个单一的字节(所以8位)。有2种掩码我需要帮助。
第一种: 假设偏移量为4,我有一个二进制1110 0001的字节。我想掩码 最后的 位的大小偏移,这样我就可以有一个1110 0000的最终字节(所以掩盖最后4位)。
第二种:比如偏移量是3,我有一个二进制为1011 0010的字节。我现在要屏蔽 第一 几位的大小偏移,所以我有一个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
.
一个更好的替代方案,适用于 offset
价值来自 1
到 32
是这样的。
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)))