如何在 C 中切换 int / _Bool

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

假设我们有一个

int
并且想要以布尔方式在
0
1
之间切换。我想到了以下几种可能性:

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. 第三个似乎有效。为什么?谁决定
    !0
    1
  2. 这些有问题吗?
  3. 还有其他的可能性吗?例如,按位运算符?
  4. 哪个提供最好的性能?
  5. 所有这些都与
    _Bool
    (或来自 stdbool.h 的
    bool
    )相同吗?如果不是,有什么区别?
c integer boolean toggle
8个回答
33
投票

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

使用这个表达方式。

来自C99 6.5.3.3/5“一元算术运算符”:

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


13
投票

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

C 标准保证

!0
1

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

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

value ^= 1;

顺便说一下,我更喜欢这个而不是

value = !value;
,因为关系运算符和相等运算符可以导致分支,而按位运算符通常不会。


12
投票
value = 1 - value; // toggle from 0 to 1 ... or 1 to 0
                   // when you know initial value is either 0 or 1

4
投票

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

  • !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% 确定它始终产生预期值。


4
投票
  1. 语言就是这样设计的。
  2. 使用第三个,其他都是正确的,但不必要的复杂,因此隐藏了意图。
  3. value = (value ^ 1) & 1;
  4. 优化后它们都是一样的。
  5. _Bool
    会有相同的结果。与 _Bool 唯一不同的是,值被强制为 1 或 0。这意味着
    bool x = 55;
    将具有值
    x == 1

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


3
投票

value = !value
似乎是最合理的,但您也可以使用
value = 1 - value
value ^= 1
。但如果
value
不是
0
1
,最后两个都会破裂。第一个仍然有效。


1
投票

您的表情

value = value == 0 ? 1 : 0;
将与
value = !value;
完全相同。您可以使用两者中的任何一个。

!0
始终是
1
并且
!(any non zero value)
也是
0


0
投票

使用按位非运算符

var = ~var;

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