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. 3つ目はうまくいくようです。なんで?!0それは誰が決めるのです1か?
  2. これらのいずれかで何か問題がありますか?
  3. 他の可能性はありますか?例えば、ビット単位の演算子?
  4. 最高のパフォーマンスを提供するのはどれですか?
  5. _Boolそれはすべて(またはboolstdbool.hから)同一でしょうか?そうでない場合、違いは何ですか?

編集:多くの貴重な情報を含む多くの素晴らしい回答、ありがとう! 残念ながら、私は1つしか受け入れることができません。

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

3つ目はうまくいくようです。なんで?!0 が 1 であると判断したのは誰ですか?

C 標準は、 であることを保証し!0ます1

他の可能性はありますか?例えば、ビット単位の演算子?

はい、排他的 OR 演算子を使用できます。

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番目のものを使用してください。他のものは正しいですが、不必要に複雑であるため、意図を隠しています。
  3. value = (value ^ 1) & 1;
  4. 最適化後はすべて同じです。
  5. _Bool同じ結果になります。_Bool との唯一の違いは、値が強制的に 1 または 0 にbool x = 55;なることです。x == 1

EDIT:私の頭がおかしいため、3の式を修正しました。人々が私のNG集を見ることができるように、私はコメントを許可します.

于 2012-10-31T08:48:08.733 に答える
3

アーキテクチャによっては、代替手段で顕著なパフォーマンスの問題が発生する可能性があります。

  • !a は、一部のアーキテクチャでは比較と分岐が必要になる場合があります。これは、'a' のパターンによってはコストがかかる可能性があります。
    • 一部のアーキテクチャでは条件付き移動 (ブランチレス) が
      ありますが、完了までにさらに 3 つの命令が必要になる場合があります (依存関係あり)。
  • 1-a 多くのアーキテクチャで 2 つの命令が必要になる可能性が高い
    • カウンターの例: 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 に答える
3

value = !valueが最も妥当なように思えますが、value = 1 - valueorも使用できますvalue ^= 1。しかし、最後の 2 つは、 isまたはvalueでない場合、両方とも壊れます。最初のものはまだ機能します。01

于 2012-10-31T08:47:10.763 に答える
1

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

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

于 2012-10-31T08:50:29.337 に答える