C / set-clear-toggle中的标志

时间:2013-08-15 10:23:19

标签: c set toggle clear flags

我对以下代码的作用感到困惑,我理解第1行设置了一个标志,第2行清除了一个标志,第3行切换了一个标志;

#include <stdio.h>
#define SCC_150_A 0x01
#define SCC_150_B 0x02
#define SCC_150_C 0x04
unsigned int flags = 0;

main () {
  flags |= SCC_150_A;  // Line 1
  flags &= ~SCC_150_B; // Line 2
  flags ^= SCC_150_C;  // Line 3
  printf("Result: %d\n",flags); // Line 4
}

我不明白第4行的输出是什么?设置/清除/切换0x01 0x020x04上的标记会产生什么影响?

2 个答案:

答案 0 :(得分:2)

宏定义了每个都需要表示一个位的常量:

macro      hex  binary
======================
SCC_150_A  0x01    001
SCC_150_B  0x02    010
SCC_150_C  0x04    100

最初flags为0。

然后它有:

  1. 按位OR设置位0。
  2. 位1由按位AND清除,倒数为SCC_150_B
  3. 位2切换(将其从0变为1)。
  4. 因此,最终结果为101 2 ,或十进制为5。

答案 1 :(得分:2)

首先,我将使用二进制数字,因为它更容易用它们来解释。最后,它与十六进制数相同。另请注意,我将变量缩短为unsigned char以使写入值更短(8位对32位)。最终结果是相似的,只是没有前导数字。

让我们从值开始:

0x01 = 0000 0001
0x02 = 0000 0010
0x04 = 0000 0100

因此在替换常量/宏之后,第一行基本上就是这样:

flags |= 0000 0001

如果任何输入值在该位置为1,则执行按位或操作,结果中的位为1。由于flags的初始值为0,这就像分配或添加一样(通常不会记住这一点)。

flags: 0000 0000
op:    0000 0001
----------------
or:    0000 0001

结果是flags设置为0000 0001

flags &= ~0000 0010

这里我们有两个操作,首先是~,即按位补码运算符。这基本上做的是翻转价值的所有部分。因此,0000 0010变为1111 1101(十六进制为0xfd)。然后你使用bitwise和operator,如果两个输入值在特定位置都是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