我是C编程的新手,遇到过位屏蔽。位掩码的一般概念和功能是什么?

例子是非常赞赏的。


当前回答

屏蔽是指保留、更改或删除所需的部分信息。让我们来看看一个图像掩蔽操作;就像这个掩蔽操作是去除皮肤以外的任何东西:

在本例中,我们执行的是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,它是偶数。因此,通过对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

其他回答

屏蔽是指保留、更改或删除所需的部分信息。让我们来看看一个图像掩蔽操作;就像这个掩蔽操作是去除皮肤以外的任何东西:

在本例中,我们执行的是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,它是偶数。因此,通过对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

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

屏蔽是对一个值应用掩码的行为。这可以通过以下方式实现:

按位和,以提取值中的位的子集 按位ORing,以便设置值中的位的子集 按位XORing,以便切换值中的一个位子集

下面是一个提取值中比特子集的例子:

Mask:   00001111b
Value:  01010101b

对值应用掩码意味着我们希望清除第一个(高)位,并保留最后一个(低)位。因此,我们提取了较低的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;