我是C编程的新手,遇到过位屏蔽。位掩码的一般概念和功能是什么?
例子是非常赞赏的。
我是C编程的新手,遇到过位屏蔽。位掩码的一般概念和功能是什么?
例子是非常赞赏的。
当前回答
掩码定义了你想要保留哪些位,以及你想要清除哪些位。
屏蔽是对一个值应用掩码的行为。这可以通过以下方式实现:
按位和,以提取值中的位的子集 按位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;
其他回答
屏蔽是指保留、更改或删除所需的部分信息。让我们来看看一个图像掩蔽操作;就像这个掩蔽操作是去除皮肤以外的任何东西:
在本例中,我们执行的是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;