我对 C 编程相当陌生,我遇到了位掩码。有人可以向我解释位掩码的一般概念和功能吗?非常感谢示例。
2 回答
掩码定义要保留哪些位,以及要清除哪些位。
掩码是将掩码应用于值的行为。这是通过执行以下操作来完成的:
- 按位与运算以提取值中的位子集
- 按位或运算以设置值中的位子集
- 按位异或,以切换值中的位子集
下面是一个提取值中位子集的示例:
Mask: 00001111b
Value: 01010101b
将掩码应用于值意味着我们要清除前(高)4 位,并保留最后(低)4 位。因此,我们提取了低 4 位。结果是:
Mask: 00001111b
Value: 01010101b
Result: 00000101b
屏蔽是使用 AND 实现的,所以在 C 中我们得到:
uint8_t stuff(...) {
uint8_t mask = 0x0f; // 00001111b
uint8_t value = 0x55; // 01010101b
return mask & value;
}
这是一个相当常见的用例:从较大的单词中提取单个字节。我们将字中的高位定义为第一个字节。我们为此使用两个运算符&
, 和>>
(右移)。这就是我们如何从 32 位整数中提取四个字节的方法:
void more_stuff(uint32_t value) { // Example value: 0x01020304
uint32_t byte1 = (value >> 24); // 0x01020304 >> 24 is 0x01 so
// no masking is necessary
uint32_t byte2 = (value >> 16) & 0xff; // 0x01020304 >> 16 is 0x0102 so
// we must mask to get 0x02
uint32_t byte3 = (value >> 8) & 0xff; // 0x01020304 >> 8 is 0x010203 so
// we must mask to get 0x03
uint32_t byte4 = value & 0xff; // here we only mask, no shifting
// is necessary
...
}
请注意,您可以切换上述运算符的顺序,您可以先执行掩码,然后执行移位。结果是一样的,但现在你必须使用不同的掩码:
uint32_t byte3 = (value & 0xff00) >> 8;
掩蔽意味着保留/更改/删除所需的信息部分。让我们看一个图像屏蔽操作;就像-这个遮罩操作正在去除任何不是皮肤的东西-
在这个例子中,我们正在做AND操作。还有其他掩码运算符- OR,XOR。
位掩码意味着对位施加掩码。这是一个带有AND的位掩码-
1 1 1 0 1 1 0 1 [input] (&) 0 0 1 1 1 1 0 0 [mask] ------------------------------ 0 0 1 0 1 1 0 0 [output]
因此,只剩下中间的 4 位(因为这些位1
在此掩码中)。
让我们用XOR来看看-
1 1 1 0 1 1 0 1 [input] (^) 0 0 1 1 1 1 0 0 [mask] ------------------------------ 1 1 0 1 0 0 0 1 [output]
现在,中间的 4 位被翻转(1
成为0
,0
成为1
)。
因此,使用位掩码我们可以访问各个位 [示例]。有时,这种技术也可用于提高性能。以此为例——
bool isOdd(int i) {
return i%2;
}
这个函数告诉一个整数是奇数还是偶数。我们可以使用位掩码更高效地实现相同的结果-
bool isOdd(int i) {
return i&1;
}
简短说明:如果二进制数的最低有效位1
是奇数;因为0
它会是平的。因此,通过与我们进行AND操作,1
我们将删除除最低有效位之外的所有其他位,即:
55 -> 0 0 1 1 0 1 1 1 [input] (&) 1 -> 0 0 0 0 0 0 0 1 [mask] --------------------------------------- 1 <- 0 0 0 0 0 0 0 1 [output]