it-swarm.com.de

Wie kann man ein int/_Bool in C umschalten?

Angenommen, wir haben eine int und möchten sie zwischen 0 und 1 boolesch umschalten. Ich dachte an folgende Möglichkeiten:

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. Der dritte scheint zu funktionieren. Warum? Wer entscheidet, dass !01 ist?
  2. Stimmt etwas mit diesen nicht?
  3. Gibt es noch andere Möglichkeiten? z.B. bitweise Operatoren?
  4. Welches bietet die beste Leistung?
  5. Wäre das alles mit _Bool (oder bool von stdbool.h) identisch? Wenn nein, was sind die Unterschiede?

EDIT: Viele tolle Antworten mit vielen wertvollen Informationen, danke! Leider kann ich nur eine akzeptieren.

13
riha

value = !value; drückt aus, was Sie direkt tun möchten, und tut genau das, was Sie per Definition tun möchten.

Verwenden Sie diesen Ausdruck.

Ab C99 6.5.3.3/5 "Unäre arithmetische Operatoren":

Das Ergebnis des logischen Negationsoperators! ist 0, wenn der Wert seines Operanden ungleich 0 ist, 1, wenn der Wert seines Operanden gleich 0 vergleicht. Das Ergebnis hat den Typ int. Der Ausdruck! E entspricht Bis (0 == E).

25
Michael Burr

Der dritte scheint zu funktionieren. Warum? Wer entscheidet, dass! 0 ist 1?

C Standard garantiert, dass !0 der 1 ist.

Gibt es noch andere Möglichkeiten? z.B. bitweise Operatoren?

Ja, Sie können den exklusiven Operator OR verwenden:

value ^= 1;

Übrigens bevorzuge ich value = !value;, da relationale Operatoren und Gleichheitsoperatoren zu Verzweigungen führen können und bitweise Operatoren normalerweise nicht. 

11
ouah

value = !value scheint der sinnvollste, aber Sie können auch value = 1 - value oder value ^= 1 verwenden. Die letzten beiden würden jedoch beide brechen, wenn value nicht 0 oder 1 ist. Der erste würde noch funktionieren.

3
detunized
  1. die Sprache wurde so gestaltet.
  2. Verwenden Sie die dritte, die anderen sind richtig, aber unnötig kompliziert und daher die Absicht verbergen.
  3. value = (value ^ 1) & 1;
  4. Sie sind alle nach der Optimierung gleich. 
  5. _Bool hätte die gleichen Ergebnisse. Das einzige, was bei _Bool anders ist, ist, dass die Werte gezwungen werden, entweder 1 oder 0 zu sein. Das bedeutet, dass bool x = 55; den Wert x == 1 hat.

BEARBEITEN: Die Formel in 3 wurde aufgrund meines Brainfarts korrigiert. Ich lasse die Kommentare, damit die Leute meinen Blooper sehen können.

3

Je nach Architektur können mit den Alternativen Leistungsprobleme auftreten:

  • In einigen Architekturen kann ein Vergleich und eine Verzweigung erforderlich sein, was je nach dem Muster von 'a' teuer sein kann.
    • bei einigen Architekturen gibt es eine bedingte Verschiebung (die verzweigungslos ist), aber
      , für die möglicherweise noch 3 Anweisungen erforderlich sind (mit Abhängigkeiten)
  • 1-a benötigt höchstwahrscheinlich zwei Anweisungen in vielen Architekturen
    • zählerbeispiel: ARM hat umgekehrte SubtraktionRSB% r0,% r0, # 1
  • 1 ^ a kann in vielen Architekturen mit einer einzigen Anweisung implementiert werden
  • a = (a + 1)% 2 wird höchstwahrscheinlich auf a = (a + 1) & 1 optimiert, was 2 Anweisungen erfordert

Die erste Regel der Optimierung ist jedoch, dass ein nicht funktionierender Code nicht optimiert wird. Um! A durch ein ^ 1 zu ersetzen, muss man 100% sicher sein, dass er immer den erwarteten Wert liefert.

3
Aki Suihkonen

Ihr Ausdruck value = value == 0 ? 1 : 0; funktioniert genauso wie value = !value;. Sie können eine der beiden verwenden.

!0 ist immer 1 und auch !(any non zero value) ist 0

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

In C # können Sie Math.Abs(value -1) verwenden, um als Ganzzahlen zwischen Null und Eins umzuschalten.

0
tkerwood