存在标志定义:
flag1=1
flag2=2
flag3=4
flag4=8
...
flagN=2^(N-1)
flag=flag1+flag2+...+flagN
如果flagI
没有设置,它 eq0
我有flag
。哪种方法可以轻松检查,例如flag2
定义?
存在标志定义:
flag1=1
flag2=2
flag3=4
flag4=8
...
flagN=2^(N-1)
flag=flag1+flag2+...+flagN
如果flagI
没有设置,它 eq0
我有flag
。哪种方法可以轻松检查,例如flag2
定义?
请注意,在每个标志中,只有一位设置为 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
您可以对所有标志执行此操作。
范围是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)
+-------------------------------+
Boolean isSet (flags, flagN){
Return (flags & flagN) != 0;
}
Flags 是标志向量,flagN 是你要检查的标志
值得更深入地了解位掩码和标志的概念。然后,您可以使用您的想象力有效地表示状态。(以下仅举例说明)
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 并评估上述操作。