如何优化以下代码?
( (kbd_flags & KBD_FLAG_SHIFT) && !(kbd_flags & KBD_FLAG_CAPS))
|| (!(kbd_flags & KBD_FLAG_SHIFT) && (kbd_flags & KBD_FLAG_CAPS))
基本上,我想检查是否设置了KBD_FLAG_SHIFT或KBD_FLAG_CAPS,但两者都没有。
答案 0 :(得分:1)
我想在做一些研究后分享我的解决方案。佐多的表达可以简化为
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;
这是有效的,因为设计了两个补码表示法。例如,如果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
是持有要测试的标志的整数):
int f, x;
for (f = 0; f <= F + 1; f++) {
x = f & (A | B | C | D | E | F);
printf("0x%02x %d%d%d%d%d%d -> %d\n", f
, (f & A) == A, (f & B) == B, (f & C) == C
, (f & D) == D, (f & E) == E, (f & F) == F
, x && (x & x - 1) == 0);
}
此代码将输出以下内容:
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
如您所见,如果设置了一位,x && (x & x - 1) == 0
为true
。
答案 1 :(得分:0)
您可以使用此
(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
答案 2 :(得分:0)
更清楚地回答。
(kbd_flags & KBD_FLAG_SHIFT) ^ (kbd_flags & KBD_FLAG_CAPS)
这应该有用。