int val = 0xCAFE测试最后四位(LSB)中至少有三位是否打开

时间:2013-11-03 21:38:36

标签: c bit-manipulation mask

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

3 个答案:

答案 0 :(得分: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,所以我会留下这个来试图理解。

答案 1 :(得分:1)

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

假设您有一个变量something和一个mask,两者都是unsigned值:something & mask将返回一个位为0的值,其中掩码为0,以及掩码为something的{​​{1}}中的值。这是和掩码

要理解为什么使用这些特定值,您必须回想一下按位操作(1& ...)在C中的工作方式。当您编写|时,则使用指定的逻辑运算符有序地组合两个变量的相应位。例如,如果a & ba10001010b,则00000011a & b(有序,00000010)。

如果您了解这一点,那么您可以了解这些面具将选择的内容。考虑他们的二进制表示:

1 and 0, 0 and 0, 0 and 0, 0 and 0, 1 and 0, 0 and 0, 1 and 1, 0 and 1

这是用于和屏蔽,用于提取值(请参阅您链接的答案)。 xor 屏蔽功能类似,只需回忆逻辑功能的行为。

答案 2 :(得分: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);
    }
}