首先,我将使用二进制数,因为用它们更容易解释。最后它与十六进制数字相同。另请注意,我将变量缩短为unsigned char
要写下的值更短(8 位与 32 位)。最终结果是相似的,只是没有前导数字。
让我们从值开始:
0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100
所以在替换常量/宏之后,第一行基本上是这样的:
flags |= 0000 0001
这将执行按位或运算1
,如果任何输入值1
位于该位置,则结果中的位为 。由于flags
being的初始值0
,这将像分配或添加一样工作(通常不会,请记住这一点)。
flags: 0000 0000
op: 0000 0001
----------------
or: 0000 0001
结果flags
被设置为0000 0001
。
flags &= ~0000 0010
这里我们有两个操作,第一个~
是按位补码运算符。这本质上是翻转值的所有位。因此0000 0010
变成1111 1101
(0xfd
十六进制)。然后您使用按位和运算符,其中仅1
当两个输入值也1
位于特定位置时才将结果位设置为。如您所见,这实际上会导致将右侧的第二位设置为,0
而不会触及任何其他位。
flags: 0000 0001
op: 1111 1101
----------------
and: 0000 0001
因此,此操作的结果是0000 0001
(0x01
十六进制)。
flags ^= 0000 0100
最后一个操作是按位异或(xor),1
只有当输入位不匹配(即它们不同)时才会设置一个位。这导致切换操作数中设置的位的简单行为。
flags: 0000 0001
op: 0000 0100
----------------
xor: 0000 0101
在这种情况下,结果将是0000 0101
(0x05
十六进制)。
为了澄清最后一个操作,因为我认为 xor 可能是这里最难理解的,让我们把它切换回来:
flags: 0000 0101
op: 0000 0100
----------------
xor: 0000 0001
如您所见,右边的第三位在两个输入中相等,因此结果将是0
而不是1
。