C语言 如何在 C 中切换 int / _Bool

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13154073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:14:46  来源:igfitidea点击:

How to toggle an int / _Bool in C

cbooleaninttoggle

提问by riha

Suppose we have an intand want to toggle it between 0and 1in a boolean fashion. I thought of the following possibilities:

假设我们有一个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. The third one seems to work. Why? Who decides that !0is 1?
  2. Is something wrong with any of these?
  3. Are there other possibilities? e.g. bitwise operators?
  4. Which offers the best performance?
  5. Would all that be identical with _Bool(or boolfrom stdbool.h)? If not, what are the differences?
  1. 第三个似乎有效。为什么?谁决定那!01
  2. 这些有什么问题吗?
  3. 还有其他可能吗?例如按位运算符?
  4. 哪个提供最好的性能?
  5. 所有这些都与_Bool(或bool来自 stdbool.h)相同吗?如果不是,有什么区别?

EDIT: Many great answers with lots of valuable information, thanks! Unfortunately, I can only accept one.

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

回答by Michael Burr

value = !value;expresses what you want to do directly, and it does exactly what you want to do by definition.

value = !value;直接表达你想做什么,它按照定义做你想做的。

Use that expression.

用那个表情。

From C99 6.5.3.3/5 "Unary arithmetic operators":

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

The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).

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

回答by ouah

The third one seems to work. Why? Who decides that !0 is 1?

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

C Standard guarantees that !0is 1.

C 标准保证!01.

Are there other possibilities? e.g. bitwise operators?

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

Yes, you can use the exclusive OR operator:

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

value ^= 1;

value ^= 1;

By the way I prefer this to value = !value;as relational and equality operators can result to branching and bitwise operators usually do not.

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

回答by Patrick Schlüter

  1. the language was designed that way.
  2. Use the 3rd one, the others are right but unnecessarly complicated and therefore hiding the intent.
  3. value = (value ^ 1) & 1;
  4. They're all the same after optimisation.
  5. _Boolwould have the same results. The only thing different with _Bool is that values are coerced to be either 1 or 0. Meaning that bool x = 55;will have the value x == 1
  1. 语言就是这样设计的。
  2. 使用第三个,其他是对的,但不必要地复杂,因此隐藏了意图。
  3. value = (value ^ 1) & 1;
  4. 优化后都一样。
  5. _Bool会有相同的结果。与 _Bool 唯一不同的是值被强制为 1 或 0。这意味着bool x = 55;将具有值x == 1

EDIT: Corrected the formula in 3 because of my brainfart. I let the comments so that people can see my blooper.

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

回答by Scott Stensland

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

回答by Aki Suihkonen

There can be noticeable performance issues with the alternatives depending on the architecture:

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

  • !a might need in some architectures comparison and branching, which can be expensive depending on the pattern of 'a'
    • on some architectures there is conditional move (which is branchless), but
      which may require still 3 instructions to complete (with dependencies)
  • 1-a most likely needs two instructions in many architectures
    • counter example: ARM has reverse subtraction RSB%r0, %r0, #1
  • 1^a can be implemented in many architecture with a single instruction
  • a=(a+1) % 2 will be most likely optimized to a=(a+1)&1, which requires 2 instructions
  • !a 在某些架构中可能需要比较和分支,这可能会很昂贵,具体取决于 'a' 的模式
    • 在某些架构上有条件移动(无分支),但
      可能仍需要 3 条指令才能完成(有依赖关系)
  • 1-a 在许多架构中很可能需要两条指令
    • 反例:ARM 有反向减法RSB%r0, %r0, #1
  • 1^a 可以通过一条指令在许多架构中实现
  • a=(a+1) % 2 最有可能优化为 a=(a+1)&1,这需要 2 条指令

But anyway the first rule of optimization is that don't optimize a non working code. To replace !a with a^1, one has to be 100% certain that it produces always the expected value.

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

回答by detunized

value = !valueseems the most reasonable one, but you can also use value = 1 - valueor value ^= 1. But the last two would both break if valueis not 0or 1. The first one would still work.

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

回答by CCoder

Your expression value = value == 0 ? 1 : 0;will work exactly like value = !value;. You can use any of the two.

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

!0is always 1and also !(any non zero value)is 0

!0永远1!(any non zero value)0

回答by tkerwood

In C# you can use Math.Abs(value -1)to toggle between zero and one as integers.

在 C# 中,您可以使用Math.Abs(value -1)整数在 0 和 1 之间切换。