我正在尝试自己学习C。我遇到了这个练习,我正在学习理解它。我已经阅读了有关屏蔽位的信息,为了获得最后四个位,我们应该执行 val&0xF。我也阅读了这篇文章什么是位屏蔽?. 我需要解释的部分是为什么可能的值是 0x7,0xB,0xD,0xE,0xF。我正在研究答案,我已经阅读了各种文章。如果有人愿意向我解释这部分,我将不胜感激。
3 回答
因为这些都是最后四位中至少三位打开的所有可能数字。如果你记下从 0 到 15 的每一个二进制数,你会看到它们至少设置了最后四位中的三位:
- 0111 (0x7)
- 1011 (0xB)
- 1101 (0xD)
- 1110 (0xE)
- 1111 (0xF)
可以这样想:从 0 到 6 的每个二进制数最多设置 2 位:
- 0 (0)
- 1 (1)
- 10 (2)
- 11 (3)
- 100 (4)
- 101 (5)
- 110 (6)
因此,没有一个符合规则。从 7 到 15,我们有:
- 111 (7)
- 1000 (8)
- 1001 (9)
- 1010 (10)
- 1011 (11)
- 1100 (12)
- 1101 (13)
- 1110 (14)
- 1111 (15)
从这些中,只有 7、11、13、14 和 15 设置了最后四位中的三个。
这种方法很容易实现:
int chk_last_bits2(unsigned x) {
return ((x & 0x7) == 0x7) ||
((x & 0xB) == 0xB) ||
((x & 0xD) == 0xD) ||
((x & 0xE) == 0xE) ||
((x & 0xF) == 0xF);
}
请注意,我们必须明确测试每种情况的相等性。例如,x & 0xB
将为每个设置了任何位的数字返回一个非零值1011
。这不是我们想要的,我们希望所有这些都开启,这可以通过平等进行测试。
另一种可能的解决方案是:
int chk_last_bits(unsigned x) {
int i, j;
for (i = 1, j = 0; i < 32; i <<= 1)
if (i & x)
j++;
return j >= 3;
}
由于您正在学习C,因此我将把这个留给您尝试理解。
屏蔽意味着过滤位并仅保留其中一些感兴趣的位,正如您将理解的那样。
假设您有一个变量something
和 a mask
,它们都是unsigned
值:something & mask
将返回一个值,该值的位是0
掩码所在的位置0
以及它们在something
掩码所在位置的值1
。这是和面具。
要理解为什么要使用这些特定值,您必须回忆一下按位运算 ( &
, |
...) 在 C 中是如何工作的。当您编写a & b
时,两个变量的相应位会使用指定的逻辑运算符按顺序组合。例如,如果a
is10001010
和b
is 00000011
,则a & b
is 00000010
(orderly, 1 and 0, 0 and 0, 0 and 0, 0 and 0, 1 and 0, 0 and 0, 1 and 1, 0 and 1
)。
如果你理解了这一点,那么你就可以理解这些面具会选择什么。考虑它们的二进制表示:
0x7 --> ...00000111 --> the three LSBs 0xb --> ...00001011 --> the first, second and fourth LSBs 0xd --> ...00001101 --> the first, third and fourth LSBs 0xe --> ...00001110 --> the second, third and fourth LSBs 0xf --> ...00001111 --> the 4 LSBs
这是 for and masking,用于提取值(请参阅您链接的答案)。 xor和or掩码的工作方式类似,只需回忆一下逻辑函数的行为方式。
#include <stdio.h>
int main()
{
/*
32 Bit binary: 00000000000000001100101011111110
Decimal: 51966
*/
int val = 0xCAFE;
/*
Note:
First it does loop, after that it shifts the bits of `i`,
so `i` is 1 at the beginning.
When shifting operator appears always think of bits.
Step 1
Decimal: i = 1
32 Bit binary: 00000000000000000000000000000001
Step 2
Decimal: 1 << 1 = 2
32 Bit binary: 00000000000000000000000000000010
Step 3
Decimal: 2 << 1 = 4
32 Bit binary: 00000000000000000000000000000100
... and so on ... 1, 2, 4, 8, 16, 32, stop.
This indicates 2^n.
----------------------------------------------------------------
Inside the for loop we run the AND operator to find out
which bits are `on` and which are `off`.
AND only works if both are true.
Step 1:
Last bit
00000000000000000000000000000001
AND 00000000000000001100101011111110
---------------------------------
00000000000000000000000000000000
Decimal: 1
Second last bit
Step 2:
00000000000000000000000000000010
AND 00000000000000001100101011111110
---------------------------------
00000000000000000000000000000010
Decimal: 2
... and so on ...
As we can see we gradually check for last 4 bits until
we reach the 4th loop 2^4 = 32 and the loop stops.
*/
int i;
for (i = 1; i < 32; i = i << 1) {
/*
You can simply add a counter over here
and return the value at the end.
*/
printf("%d\n", i & val);
}
}