C语言中的标志 set-clear-toggle

问题描述 投票:0回答:2

我很困惑下面的代码是做什么的,我理解第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行的输出会是什么?设置clearingtoggling标志的效果是什么?0x01 0x020x04?

c set toggle flags
2个回答
2
投票

这些宏定义的常量,每个常量都需要一个位来表示。

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

初始化 flags 是0。

那么它有。

  1. 位数0被位数OR设置,位数1被位数AND清除
  2. 位1被位与位的AND清除,位的倒数为 SCC_150_B.
  3. 位2拨动(将其从0变成1)。

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


2
投票

首先,我打算用二进制数,因为用它们解释起来更容易。最后,用十六进制数也是一样的。另外,请注意,我把变量缩短为 unsigned char 以获得一个较短的值(8位与32位)。最终的结果是相似的,只是没有前导数字。

让我们从值开始。

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

所以在替换了constantmacro之后,第一行基本上是这样的:

flags |= 0000 0001

这是在执行一个位运算,结果中的一个位是: 1,如果任何一个输入值是 1 在该位置。由于初始值为 flags0这将像赋值或加法一样工作(一般情况下不会,请记住这一点)。

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

结果是 flags 被设定为 0000 0001.

flags &= ~0000 0010

这里我们有两个操作,首先是 ~,即位补运算符。这实质上是对值的所有位进行翻转。因此 0000 0010 成为 1111 1101 (0xfd 的十六进制)。) 然后你使用的是bitwise和运算符,其中一个结果位只设置为 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.

© www.soinside.com 2019 - 2024. All rights reserved.