0

我对以下代码的作用感到困惑,我知道第 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 0x02在和上设置/清除/切换标志有什么影响0x04

4

2 回答 2

3

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

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

初始flags为 0。

然后它有:

  1. 位 0 由按位或设置。
  2. 位 1 由与 的倒数进行按位与清零SCC_150_B
  3. 位 2 切换(将其从 0 变为 1)。

因此,最终结果是 101 2或十进制的 5。

于 2013-08-15T10:26:27.803 回答
2

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

让我们从值开始:

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

所以在替换常量/宏之后,第一行基本上是这样的:

flags |= 0000 0001

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

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

结果flags被设置为0000 0001

flags &= ~0000 0010

这里我们有两个操作,第一个~是按位补码运算符。这本质上是翻转值的所有位。因此0000 0010变成1111 11010xfd十六进制)。然后您使用按位和运算符,其中仅1当两个输入值也1位于特定位置时才将结果位设置为。如您所见,这实际上会导致将右侧的第二位设置为,0而不会触及任何其他位。

flags: 0000 0001
op:    1111 1101
----------------
and:   0000 0001

因此,此操作的结果是0000 00010x01十六进制)。

flags ^= 0000 0100

最后一个操作是按位异或(xor),1只有当输入位不匹配(即它们不同)时才会设置一个位。这导致切换操作数中设置的位的简单行为。

flags: 0000 0001
op:    0000 0100
----------------
xor:   0000 0101

在这种情况下,结果将是0000 01010x05十六进制)。

为了澄清最后一个操作,因为我认为 xor 可能是这里最难理解的,让我们把它切换回来:

flags: 0000 0101
op:    0000 0100
----------------
xor:   0000 0001

如您所见,右边的第三位在两个输入中相等,因此结果将是0而不是1

于 2013-08-15T10:41:53.647 回答