1

存在标志定义:

flag1=1
flag2=2
flag3=4
flag4=8
...
flagN=2^(N-1)

flag=flag1+flag2+...+flagN

如果flagI没有设置,它 eq0

我有flag。哪种方法可以轻松检查,例如flag2定义?

4

4 回答 4

4

请注意,在每个标志中,只有一位设置为 1,其他位设置为 0。

flag1 = 000 ... ... 0001
flag2 = 000 ... ... 0010
flag3 = 000 ... ... 0100
// and like this

因此,如果您按位与,flag & flag2则只有在定义时结果才会是非零的flag2

r = flag & flag2;
if r != 0 then flag2 is defined

您可以对所有标志执行此操作。

于 2012-08-05T08:50:55.410 回答
4

回答你的问题

范围是flag多少?如果低于 2^64-1,几乎所有方法都可以。

正如@taskinoor 所发布的,您应该注意到:

flag1 = 000 ... ... 0001 

flag2 = 000 ... ... 0010 

flag3 = 000 ... ... 0100

换句话说,

flag[n] = 1 << (n-1)

所以,如果你想检查所有位,一个for循环并且bitwise operation足够快来解决你的问题。像这样(假设你可以理解C/C++并且 flag 小于 2^32,这可以由C/C++unsigned int中的 an 持有):

void check(unsigned int flag)
{
  for (int i = 0; i < 32; ++i)
    if ((flag & (1 << i)) != 0)
      printf("flag%d defined!\n", i+1);
}

flag它是 O(k),其中 k 是二进制类型的长度。对于unsigned int,它是 O(32) = O(1),几乎在恒定时间内。

如果您只想计算定义了多少个标志:

我不知道你的目的是什么。如果您只想计算定义了多少个标志并且flag小于 2^64,那么以下方法很棒(假设unsigned int也是如此):

unsigned int count_bit(unsigned int x)
{
  x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
  x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
  x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
  x = (x & 0x0000FFFF) + ((x >> 16)& 0x0000FFFF);
  return x;
}

如果您调用 count_bit(1234567890),它将返回 12。

让我解释一下这个算法。

该算法基于Divide and Conquer Algorithm. 假设有一个 8 位整数 213(二进制 11010101),算法是这样工作的(每次合并两个相邻块):

+-------------------------------+
| 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |  <- x
|  1 0  |  0 1  |  0 1  |  0 1  |  <- first time merge
|    0 0 1 1    |    0 0 1 0    |  <- second time merge
|        0 0 0 0 0 1 0 1        |  <- third time ( answer = 00000101 = 5)
+-------------------------------+
于 2012-08-05T12:34:29.997 回答
0
Boolean isSet (flags, flagN){
   Return (flags & flagN) != 0;
}

Flags 是标志向量,flagN 是你要检查的标志

于 2012-08-05T08:47:10.523 回答
0

值得更深入地了解位掩码和标志的概念。然后,您可以使用您的想象力有效地表示状态。(以下仅举例说明)

 First -Define the bitmask :          0x0000001c 

当您对掩码执行“与”操作时,得到非零值的二进制字符串是什么?

这些是您的有效标志值。

此位掩码的有效标志值: 0x0000001c,0x00000014,0x00000018,0x00000004,0x00000008,etc ..

因此,在您的应用程序中,如果您可以执行以下操作:

flagvariable |= flagvalue1  ->Enable a particular flag.  
if( flagvariable & maskvalue)   :Check if a mask is enabled  :  

然后您需要检查的不同情况:

if(flagvariable &maskvalue ==flagvalue1)    { do something}
else  
if(flagvariable &maskvalue ==flagvalue2) {do something else}    

flagvariable &= `flagvalue1  : Clear the flag  

为了更清楚地了解标志和位掩码,只需进入 gdb 并执行 p /t 并评估上述操作。

于 2012-08-05T09:54:19.967 回答