逐位,逐位屏蔽:这里出了什么问题

Bitwise, bitmasking: whats wrong here?

本文关键字:什么 问题 这里 屏蔽 逐位      更新时间:2023-10-16

我想通过bitmask跟踪一些选项,并从这个答案中借用了bitmask值,但它们似乎无法协同工作。

#include <iostream>
#define OP1 0x00003FFFUL
#define OP2 0x00007FFFUL
#define OP3 0x0000FFFFUL
int main() {
        unsigned long params = 0; // .
        params |= OP3;
        if ( (params & OP1) == OP1)
                std::cout << "Whoa. Lame maskingn";
}

这是一个类型问题,还是这种方法不能用于一次持有一个以上的选项(OP1、OP2和OP3都希望保持在同一个params中)?

对于选项,您应该使用其他掩码,即不重叠的掩码,例如:

   #define OP1 0x000000FUL
   #define OP2 0x00000F0UL
   #define OP3 0x0000F00UL

或者(在这种情况下,您可以存储尽可能多的可用位选项):

   #define OP1 0x0000001UL
   #define OP2 0x0000002UL
   #define OP3 0x0000004UL
   //ETC...

您的掩码将永远无法正常工作,因为如果设置了OP3,则将包含OP1和OP2(如果使用OP2,则将隐含OP1):

     FFFF = 1111111111111111
  &  3FFF = 0011111111111111
     -----------------------
     3FFF = 0011111111111111

您粘贴的示例中的掩码旨在推断UL的最后几位。

您认为0xF&0x3?

它有所有的"选项"。问题是,OP1、OP2和OP3中的位重叠。OP3也设置了OP1和OP2的所有位。因此,OP3&OP1将等于OP1;OP2将等于OP2。因此,出现了混乱。如果OP1=1,OP2=2,OP3=4,则不会出现这种情况。然后你还必须将标志设置为

params |= OP1 | OP2 | OP3

但是,如果您要求OP1、OP2和OP3是您所提供的,那么您的比特掩码代码就没有问题。

这个实现可能很奇怪,除非你有其他没有显示的东西(似乎不太可能,因为它来自另一个问题)。更好的解决方案可能是枚举您的位掩码。类似于:

enum values {
    aaa = 1 << 0,
    bbb = 1 << 1,
    ccc = 1 << 2,
    ab = aaa | bbb,
    ac = aaa | ccc,
    abc = aaa | bbb | ccc,
    bc = bbb | ccc, };

然后可以像一样使用

unsigned int var = abc;
if (var & aaa) {
    cout << "OK";
}

输出"OK"

这为您提供了可能需要的重叠值,同时也清楚地定义了它们之间的关系。如果你想变得更漂亮,你可以做:

namespace blah {
enum values {
    aaa = 1 << 0,
    bbb = 1 << 1,
    ccc = 1 << 2,
    ab = aaa | bbb,
    ac = aaa | ccc,
    abc = aaa | bbb | ccc,
    bc = bbb | ccc,
};
}

这将使您能够像一样使用它

unsigned int var = blah::abc;
if (var & blah::aaa) {
    cout << "OK";
}

再次输出"OK"

如果你使用uint的全宽和许多标志的组合(它不会打乱你的主命名空间),这会变得很好。

您没有初始化参数。

尝试:

unsigned long params = 0;