18

假设我们有一个并且想要以布尔方式在和int之间切换。我想到了以下几种可能:01

int value = 0; // May as well be 1

value = value == 0 ? 1 : 0;
value = (value + 1) % 2;
value = !value; // I was curious if that would do...
  1. 第三个似乎有效。为什么?是谁决定!01
  2. 这些有什么问题吗?
  3. 还有其他可能性吗?例如按位运算符?
  4. 哪个提供最佳性能?
  5. 所有这些都与_Bool(或bool来自stdbool.h)相同吗?如果不是,有什么区别?

编辑:很多很好的答案,有很多有价值的信息,谢谢!不幸的是,我只能接受一个。

4

8 回答 8

33

value = !value;直接表达你想要做的事情,并且它完全按照定义做你想做的事情。

使用该表达式。

从 C99 6.5.3.3/5“一元算术运算符”开始:

逻辑否定运算符的结果!如果其操作数的值比较不等于 0,则为 0,如果其操作数的值比较等于 0,则为 1。结果的类型为 int。表达式 !E 等价于 (0==E)。

于 2012-10-31T08:43:49.803 回答
12

第三个似乎有效。为什么?谁决定!0 是 1?

C 标准保证!01.

还有其他可能性吗?例如按位运算符?

是的,您可以使用异或运算符:

value ^= 1;

顺便说一句,我更喜欢这种方式, value = !value;因为关系和相等运算符会导致分支,而按位运算符通常不会。

于 2012-10-31T08:45:15.120 回答
8
value = 1 - value; // toggle from 0 to 1 ... or 1 to 0
                   // when you know initial value is either 0 or 1
于 2017-10-01T21:38:42.713 回答
4
  1. 语言就是这样设计的。
  2. 使用第三个,其他的都是正确的,但不必要的复杂,因此隐藏了意图。
  3. value = (value ^ 1) & 1;
  4. 优化后都一样。
  5. _Bool会有相同的结果。_Bool 唯一不同的是值被强制为 1 或 0。这意味着bool x = 55;它将具有值x == 1

编辑:由于我的脑残,更正了 3 中的公式。我让评论让人们可以看到我的花絮。

于 2012-10-31T08:48:08.733 回答
3

value = !value似乎是最合理的一种,但您也可以使用value = 1 - valueor value ^= 1value但如果is not0或,最后两个都会中断1。第一个仍然可以工作。

于 2012-10-31T08:47:10.763 回答
3

根据架构的不同,替代方案可能存在明显的性能问题:

  • !a 在某些架构中可能需要比较和分支,这可能会很昂贵,具体取决于“a”的模式
    • 在某些架构上,有条件移动(无分支),但
      可能仍需要 3 条指令才能完成(有依赖关系)
  • 1-a 在许多架构中很可能需要两条指令
    • 反例:ARM 有反向减法RSB %r0, %r0, #1
  • 1^a 可以用一条指令在许多架构中实现
  • a=(a+1) % 2 最有可能优化为 a=(a+1)&1,这需要 2 条指令

但无论如何,优化的第一条规则是不要优化非工作代码。要将 !a 替换为 a^1,必须 100% 确定它始终会产生预期值。

于 2012-10-31T09:14:40.627 回答
1

您的表达式value = value == 0 ? 1 : 0;将与value = !value;. 您可以使用两者中的任何一个。

!0总是1而且!(any non zero value)也是0

于 2012-10-31T08:50:29.337 回答
0

使用按位 NOT 运算符

变种=〜变种;

于 2021-07-03T00:07:45.573 回答