什么是位屏蔽?


191

我是C语言编程的新手,遇到了位掩码。有人可以向我解释位屏蔽的一般概念和功能吗?实例是值得赞赏的。


1
您了解&|等位运算符吗?^ etc和布尔逻辑一般?掩码操作的任何解释都将要求此。
Paul R

1
是的,我了解按位运算符和布尔逻辑
Z先生2012年

2
我知道不应发布链接,但维基百科的解释很棒:en.wikipedia.org/wiki/Mask_(计算)
pevik

2
@pevik可以发布链接,但要有一些描述,以便如果链接在某天消失,则该帖子仍然可以满足其答复的目的。链接也不应仅出于促销目的。
德克斯特(Dexter)

Answers:


244

掩码定义要保留的位以及要清除的位。

遮罩是对值应用遮罩的动作。这可以通过执行以下操作来完成:

  • 按位与运算以提取值中位的子集
  • 按位或运算以设置值中位的子集
  • 按位异或,以切换值中的位子集

下面是提取值中位的子集的示例:

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;

5
很好的答案,但是也可以使用掩码来通过OR或XOR操作以及合适的掩码来设置切换特定位。
Paul R

@ user239558感谢您的示例和正确的语法。@保罗R.我会简单地说面具和值由user239558提供的例子
Mr.Z

@ Mr.Z:在C,C ++和相关语言中,您将需要按位AND运算符,其编写为&
Paul R

@ Mr.Z例如:通过屏蔽内容清除uint32_t的一个字节:#define MASK 0x000000FF .... my_uint32_t &= ~MASK
伦丁2012年

b以表示二进制文字是不是所有的编译器的支持,是否正确?
Ungeheuer

76

掩盖意味着保持/更改/删除信息的所需部分。让我们看一下图像遮罩操作;像-该遮罩操作可以去除所有非皮肤的东西-

在此处输入图片说明

在此示例中,我们正在执行AND运算。还有其他屏蔽运算符-ORXOR


位屏蔽意味着对位强加掩码。这是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成为00成为1)。


因此,使用位掩码,我们可以访问单个位[ 示例 ]。有时,此技术也可以用于提高性能。以这个为例-

bool isOdd(int i) {
    return i%2;
}

此函数告诉整数是否为奇/偶。我们可以使用bit-mask-

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]

1
另外,要将整数转换为奇数。如果是偶数:i = i | 1。当我们尝试生成类似1、3、5,...,2、4、6 ...的序列时,这非常有用
Harshit Sharma,

您还可以使用以下操作从整数中查找仅具有最低有效位的数字:lsb = i&-i
Harshit Sharma,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.