まず、説明しやすいように 2 進数を使用します。結局は16進数でも同じです。unsigned char
また、変数を短くして、書き留める値を短くしたことにも注意してください(8 ビット対 32 ビット)。最終結果は似ていますが、先頭の数字がないだけです。
値から始めましょう。
0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100
したがって、定数/マクロを置き換えた後、最初の行は基本的に次のようになります。
flags |= 0000 0001
これは、ビットごとの or 演算を実行します。1
入力値のいずれかが1
その位置にある場合、結果のビットは です。の初期値が であるためflags
、0
これは代入または追加と同じように機能します (通常はそうではないことに注意してください)。
flags: 0000 0000
op: 0000 0001
----------------
or: 0000 0001
結果はflags
に設定されてい0000 0001
ます。
flags &= ~0000 0010
ここには 2 つの演算があります。最初に~
、ビットごとの補数演算子があります。これが本質的に行うことは、値のすべてのビットを反転することです。したがって、 (16進数)に0000 0010
なります。次に、両方の入力値が特定の位置にある場合にのみ結果ビットが設定されるビットごとの and 演算子を使用しています。ご覧のとおり、これにより、基本的に右から 2 番目のビットが他のビットに触れることなく設定されます。1111 1101
0xfd
1
1
0
flags: 0000 0001
op: 1111 1101
----------------
and: 0000 0001
このため、この操作の結果は0000 0001
( 0x01
16 進数) になります。
flags ^= 0000 0100
最後の操作はビットごとの排他的論理和 (xor) で1
、入力ビットが一致しない (つまり、異なる) 場合にのみビットを設定します。これにより、オペランドに設定されたビットを切り替えるという単純な動作が発生します。
flags: 0000 0001
op: 0000 0100
----------------
xor: 0000 0101
この場合、結果は0000 0101
( 0x05
16 進数) になります。
最後の操作を明確にするために、ここでは xor が最も理解しにくいと思うので、元に戻しましょう。
flags: 0000 0101
op: 0000 0100
----------------
xor: 0000 0001
ご覧のとおり、右から 3 番目のビットは両方の入力で等しいので、結果は0
ではなくになり1
ます。