C 优化位标志检查

C 优化位标志检查,c,binary,flags,bitflags,C,Binary,Flags,Bitflags,如何优化以下代码 ( (kbd_flags & KBD_FLAG_SHIFT) && !(kbd_flags & KBD_FLAG_CAPS)) || (!(kbd_flags & KBD_FLAG_SHIFT) && (kbd_flags & KBD_FLAG_CAPS)) 基本上,我想检查是否设置了KBD\u FLAG\u SHIFT或KBD\u FLAG\u CAPS,但不能同时设置两者。您可以使用此选项 (kbd_

如何优化以下代码

   ( (kbd_flags & KBD_FLAG_SHIFT) && !(kbd_flags & KBD_FLAG_CAPS))
|| (!(kbd_flags & KBD_FLAG_SHIFT) &&  (kbd_flags & KBD_FLAG_CAPS))
基本上,我想检查是否设置了KBD\u FLAG\u SHIFT或KBD\u FLAG\u CAPS,但不能同时设置两者。

您可以使用此选项

(kbd_flags & KBD_FLAG_SHIFT) ? ((kbd_flags & KBD_FLAG_CAPS)? false : true) : ((kbd_flags & KBD_FLAG_CAPS)? true : false)
否则,您知道如何使用可以使用XOR运算符的位

A = 0000 0001
B = 0000 0000
A ^ B = 0000 0001

A = 0000 0000
B = 0000 0001
A ^ B = 0000 0001

A = 0000 0000
B = 0000 0000
A ^ B = 0000 0000

A = 0000 0001
B = 0000 0001
A ^ B = 0000 0000

在做了一些研究之后,我想分享我的解决方案。Zodoh的表达式可以简化为

kbd_flags & KBD_FLAG_SHIFT
    ? !(kbd_flags & KBD_FLAG_CAPS)
    :   kbd_flags & KBD_FLAG_CAPS
(省略不需要的括号和
true
false
表达式)

我发现的另一个有趣的方法是:

x = kbd_flags & (KBD_FLAG_SHIFT | KBD_FLAG_CAPS);
return x && (x & x - 1) == 0;
这是因为2的补码符号的设计方式。例如,如果
kbd_flags
设置为
001000
x-1
将为
000111
001000&000111
000000
。因此,
000000
等于
0
,因此返回
true
。第一个
x
表达式确保排除“未设置位”的情况

它还将使用两个以上的位标志:

#define A 0x01
#define B 0x02
#define C 0x04
#define D 0x08
#define E 0x10
#define F 0x20

x = flags & (A | B | C | D | E | F);
return x && (x & x - 1) == 0;
这里,表达式
x&&(x&x-1)==0
将是
true
当且仅当设置了
A
F
中的一个标志时

快速测试(
f
是包含要测试的标志的整数):


如您所见,
x&&(x&x-1)==0
true
如果设置了一位,则回答更清楚。

(kbd_flags & KBD_FLAG_SHIFT) ^ (kbd_flags & KBD_FLAG_CAPS)

这应该是可行的。

这不是代码的功能。它检查是否设置了任何标志。你完全正确,让我来纠正它。我不确定你关于“你可以使用XOR运算符”的意思。你能解释一下吗?异或运算符是C中的“^”符号。你可以用它来比较后面解释的位(用A和B)。像这样,你可以检查你的号码是否正确。你的宏是布尔型还是整数型?我知道C语言中的XOR运算符,我只是不明白如何使用XOR来解决我的问题。宏是位标志(无符号整数),
KBD\u标志\u移位
是0x01(01b)和0x02(10b)。KBD\u标志的类型是什么?如果您这样做,那么您将获得(kbd_标志和kbd_标志和移位)和(kbd_标志和kbd_标志\u上限)的值!(条件)这意味着条件必须为零(或false,但false=0)。因此,如果使用^,您将有以下四种情况:((1)和&&(0))|(!(0)和&(1)),现在,如果使用^,您将有以下四种情况:1^0 0^10^0 1^1只有1^0,并且0^1将返回1(=true)并通过。在代码中可能是这样的:(kbd_标志和kbd_标志和移位)^(kbd_标志和kbd_标志和上限)在我看来,这不起作用。由于可读性,让我们分别用
f
A
B
替换
kbd\u标志
、移位和
kbd\u标志
。如果
f
11b
A
01b
B
10b
),那么
(f&A)
将是
01b
(f&B)
将是
10b
。因此,
(f&a)^(f&B)
将是
11b
,评估为
true
。但是它应该是
false
,因为两个标志都已设置。因此,如果找到可能的结果,您可以添加!=11b或类似的东西?在这一点上,它开始不回答你的问题。。。它可以处理布尔值或01值。是的,它可以处理布尔值,但问题与位标志有关。在我看来,“是位标志A或B集,但不是两者都有”不能像这样解决。你完全正确。对不起,我误解了这个问题。没问题。谢谢你的时间和帮助:)
0x00 000000 -> 0
0x01 100000 -> 1
0x02 010000 -> 1
0x03 110000 -> 0
0x04 001000 -> 1
0x05 101000 -> 0
0x06 011000 -> 0
0x07 111000 -> 0
0x08 000100 -> 1
0x09 100100 -> 0
0x0a 010100 -> 0
0x0b 110100 -> 0
0x0c 001100 -> 0
0x0d 101100 -> 0
0x0e 011100 -> 0
0x0f 111100 -> 0
0x10 000010 -> 1
0x11 100010 -> 0
0x12 010010 -> 0
0x13 110010 -> 0
0x14 001010 -> 0
0x15 101010 -> 0
0x16 011010 -> 0
0x17 111010 -> 0
0x18 000110 -> 0
0x19 100110 -> 0
0x1a 010110 -> 0
0x1b 110110 -> 0
0x1c 001110 -> 0
0x1d 101110 -> 0
0x1e 011110 -> 0
0x1f 111110 -> 0
0x20 000001 -> 1
0x21 100001 -> 0
(kbd_flags & KBD_FLAG_SHIFT) ^ (kbd_flags & KBD_FLAG_CAPS)