1

我正在尝试自己学习C。我遇到了这个练习,我正在学习理解它。我已经阅读了有关屏蔽位的信息,为了获得最后四个位,我们应该执行 val&0xF。我也阅读了这篇文章什么是位屏蔽?. 我需要解释的部分是为什么可能的值是 0x7,0xB,0xD,0xE,0xF。我正在研究答案,我已经阅读了各种文章。如果有人愿意向我解释这部分,我将不胜感激。

4

3 回答 3

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,因此我将把这个留给您尝试理解。

于 2013-11-03T21:54:20.413 回答
1

屏蔽意味着过滤位并仅保留其中一些感兴趣的位,正如您将理解的那样。

假设您有一个变量something和 a mask,它们都是unsigned值:something & mask将返回一个值,该值的位是0掩码所在的位置0以及它们在something掩码所在位置的值1。这是和面具

要理解为什么要使用这些特定值,您必须回忆一下按位运算 ( &, |...) 在 C 中是如何工作的。当您编写a & b时,两个变量的相应位会使用指定的逻辑运算符按顺序组合。例如,如果ais10001010bis 00000011,则a & bis 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,用于提取值(请参阅您链接的答案)。 xoror掩码的工作方式类似,只需回忆一下逻辑函数的行为方式。

于 2013-11-03T21:52:09.340 回答
0
#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);
    }
}
于 2016-09-18T19:52:55.880 回答