什么是位屏蔽?

Mr.*_*r.Z 162 c terminology bit-manipulation bitmask bitwise-operators

我对C编程很新,我遇到了掩码.有人可以向我解释位屏蔽的一般概念和功能吗?非常感谢例子.

use*_*558 205

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

掩蔽是将掩码应用于值的行为.这是通过以下方式完成的:

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

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

Mask:   00001111b
Value:  01010101b
Run Code Online (Sandbox Code Playgroud)

将掩码应用于值意味着我们要清除第一个(更高)4位,并保留最后(较低)4位.因此我们提取了低4位.结果是:

Mask:   00001111b
Value:  01010101b
Result: 00000101b
Run Code Online (Sandbox Code Playgroud)

使用AND实现掩码,因此在C中我们得到:

uint8_t stuff(...) {
  uint8_t mask = 0x0f;   // 00001111b
  uint8_t value = 0x55;  // 01010101b
  return mask & value;
}
Run Code Online (Sandbox Code Playgroud)

这是一个相当常见的用例:从较大的单词中提取单个字节.我们将字中的高位定义为第一个字节.我们使用两个运算符&,和>>(右移).这是我们如何从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
    ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,您可以切换上面的运算符的顺序,您可以先执行掩码,然后再进行移位.结果是一样的,但现在你必须使用不同的掩码:

uint32_t byte3 = (value & 0xff00) >> 8;
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但也可以使用“或”或“异或”操作以及合适的掩码,对“设置”或“切换”特定位应用掩码。 (2认同)
  • 部分混乱可能是因为名词和动词的选择不当来描述真实情况。例如,像“Bitselector”或“TargetBits”这样的词是不是比使用“Bitmask”这个词来描述对象更合适?类似地,为了描述位操作操作,使用诸如“BitManipulate”之类的词似乎比“Masking”更合适,因为后者只对 AND 操作有意义,但对 XORING(切换位)或 OR(设置位)无效是位操作或转换,而不是屏蔽操作。 (2认同)

Min*_*mal 38

屏蔽意味着保持/更改/删除所需的信息部分.让我们看一下图像掩盖操作; 喜欢 - 这种掩蔽操作正在移除任何不是皮肤的东西 -

在此输入图像描述

我们在这个例子中做了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]
Run Code Online (Sandbox Code Playgroud)

因此,只保留中间的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]
Run Code Online (Sandbox Code Playgroud)

现在,中间的4位被翻转(1变成了0,0变成了1).


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

bool isOdd(int i) {
    return i%2;
}
Run Code Online (Sandbox Code Playgroud)

该函数告诉整数是奇数还是偶数.我们可以使用位掩码以更高的效率实现相同的结果 -

bool isOdd(int i) {
    return i&1;
}
Run Code Online (Sandbox Code Playgroud)

简短说明:如果二进制数的最低有效位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]
Run Code Online (Sandbox Code Playgroud)

  • 另外,将整数转换为奇数。如果是偶数:i=i|1。当我们尝试生成像 1, 3, 5,..., 2, 4, 6,... 这样的序列时,这会派上用场。 (4认同)