什么是位掩码?

Posted

技术标签:

【中文标题】什么是位掩码?【英文标题】:What is Bit Masking? 【发布时间】:2012-05-16 15:06:44 【问题描述】:

我对 C 编程相当陌生,但我遇到了位掩码。有人可以向我解释位掩码的一般概念和功能吗?非常感谢示例。

【问题讨论】:

我知道不应该发布链接,但***的解释很棒:en.wikipedia.org/wiki/Mask_(computing) 【参考方案1】:

掩码定义了您要保留哪些位,以及您要清除哪些位。

掩码是将掩码应用于值的行为。这是通过这样做来完成的:

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

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

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;

【讨论】:

很好的答案,但屏蔽也可以应用于 settingtoggling 具有 OR 或 XOR 操作和合适的掩码的特定位。 @Mr.Z:在 C、C++ 和相关语言中,你会使用 按位与 运算符,写成& @Mr.Z 例如:通过屏蔽内容来清除 uint32_t 的一个字节:#define MASK 0x000000FF .... my_uint32_t &= ~MASK b 表示并非所有编译器都支持二进制文字,对吗? 部分混淆可能是因为名词和动词选择不当来描述真实情况。例如,像“Bitselector”或“TargetBits”这样的词不是更适合描述对象而不是使用“Bitmask”这个词吗?类似地,为了描述位操作操作,使用诸如“BitManipulate”之类的词似乎比“Masking”这个词更合适,因为后者只对 AND 操作有意义,但对 XORING(切换位)或 OR(设置位)没有意义。是位操作或转换,但不是屏蔽操作。【参考方案2】:

屏蔽意味着保留/更改/删除所需的信息部分。让我们看一个图像屏蔽操作;就像-这个遮罩操作正在去除任何不是皮肤的东西-

在这个例子中我们正在做 AND 操作。还有其他掩码运算符 - ORXOR


Bit-Masking 意味着对位施加掩码。这是使用 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)。


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

bool isOdd(int i) 
    return i%2;

这个函数判断一个整数是奇数还是偶数。我们可以使用位掩码更高效地实现相同的结果-

bool isOdd(int i) 
    return i&1;

简短说明:如果二进制数的least significant bit为1,则为奇数;对于0,它会是偶数。因此,通过对1 执行 AND,我们将删除除最低有效位之外的所有其他位,即:

     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]

【讨论】:

另外,将整数转换为奇数。如果是偶数:i=i|1。当我们尝试生成像 1, 3, 5,..., 2, 4, 6,... 这样的序列时,这会派上用场 你也可以使用下面的操作从一个整数中找出只有最低位的数:lsb = i&-i

以上是关于什么是位掩码?的主要内容,如果未能解决你的问题,请参考以下文章

C中的位掩码

位掩码的整数和位(n)数据类型之间有啥区别吗?

如何记录位掩码

这个按位汉明(31,26)编码器如何在 C 中工作? (位掩码)

使用 SQLite 进行位掩码分组

PHP中基于位掩码获取数组值