Wie kann ich ein Flag in C entfernen?

Antworten:

339

Kurze Antwort

Sie möchten eine bitweise UND- Operation für den aktuellen Wert mit einer bitweisen NICHT- Operation des Flags ausführen, das Sie deaktivieren möchten . Ein bitweises NICHT invertiert jedes Bit (dh 0 => 1, 1 => 0).

flags = flags & ~MASK;oder flags &= ~MASK;.

Lange Antwort

ENABLE_WALK  = 0    // 00000000
ENABLE_RUN   = 1    // 00000001
ENABLE_SHOOT = 2    // 00000010
ENABLE_SHOOTRUN = 3 // 00000011

value  = ENABLE_RUN     // 00000001
value |= ENABLE_SHOOT   // 00000011 or same as ENABLE_SHOOTRUN

Wenn Sie ein bitweises UND mit bitweisem NICHT des Wertes ausführen, den Sie deaktivieren möchten.

value = value & ~ENABLE_SHOOT // 00000001

Sie tun tatsächlich:

      0 0 0 0 0 0 1 1     (current value)
   &  1 1 1 1 1 1 0 1     (~ENABLE_SHOOT)
      ---------------
      0 0 0 0 0 0 0 1     (result)
Dennis
quelle
@ Aaron: Ich bin froh, dass es geholfen hat. Ich hatte anfangs Probleme, bitweise Operationen zu verstehen, bis jemand 10 Minuten brauchte, um sie auf Papier zu erklären.
Dennis
1
@ Tennis Ich dachte, XOR würde funktionieren, um ein bereits gesetztes Flag zu entfernen. notification.sound ^= Notification.DEFAULT_SOUND;
Likejudo
3
Wie aktivieren Sie Walk? Da X | 0 == X
Unikorn
Wie @Unikorn hervorhebt, funktioniert ein Flag-Wert von Null nicht richtig, entweder wenn Sie versuchen, ihn einzuschalten, oder wenn Sie versuchen, ihn auszuschalten.
RenniePet
Um das Gehen zu aktivieren, müssen Sie nur den Lauf deaktivieren (wodurch Bit 1 auf 0 gesetzt bleibt). Stellen Sie sich die ENABLE_ * -Flaggen nicht als Dezimalzahlen vor, sondern als Binärzahlen, entweder ein oder aus. Sie können das Gehen jedoch immer noch nicht explizit aktivieren oder deaktivieren.
Jacob Degeling
82
my.emask &= ~(ENABLE_SHOOT);

um ein paar Flaggen zu löschen:

my.emask &= ~(ENABLE_SHOOT|SOME_OTHER|ONE_MORE);
Ned Batchelder
quelle
13

Es ist wichtig zu beachten, dass, wenn die zu manipulierende Variable größer als ein int ist, auch der im Ausdruck 'und nicht' verwendete Wert sein muss. Eigentlich kann man manchmal mit kleineren Typen davonkommen, aber es gibt genug seltsame Fälle, in denen es wahrscheinlich am besten ist, Typensuffixe zu verwenden, um sicherzustellen, dass die Konstanten groß genug sind.

Superkatze
quelle
5
+1 für das Auffangen des nicht offensichtlichen Eckkastens. Eine Möglichkeit, dies zu vermeiden, besteht darin, stattdessen zu verwenden flags -= flags & MY_FLAG;(oder ^=wenn Sie es vorziehen).
R .. GitHub STOP HELPING ICE
1
@R .. Ich hätte '^ =' verwendet, außer dass dadurch die Bits umgeschaltet werden und manchmal wissen Sie möglicherweise nicht, welches der vielen Flags gesetzt ist. Wenn ich sicherstellen möchte, dass die beiden am weitesten rechts stehenden Bits Null sind, z. B. my.emask: '0 1 0 1' Eingabe: '0 0 1 1' mit: '^ =' '0 1 1 0' mit: '& ~ '' 0 1 0 0 '
Hector