Jak mogę usunąć flagę w C?

Odpowiedzi:

339

Krótka odpowiedź

Chcesz wykonać operację Bitwise AND na bieżącej wartości z operacją Bitwise NOT flagi, którą chcesz cofnąć . Bitowe NIE odwraca każdego bitu (tj. 0 => 1, 1 => 0).

flags = flags & ~MASK;lub flags &= ~MASK;.

Długa odpowiedź

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

Kiedy wykonujesz Bitwise AND z Bitwise NOT wartości, którą chcesz cofnąć.

value = value & ~ENABLE_SHOOT // 00000001

faktycznie robisz:

      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
źródło
@Aaron: Cieszę się, że pomogło. Początkowo miałem problemy ze zrozumieniem operacji bitowych, dopóki komuś nie zajęło 10 minut, aby wyjaśnić to na papierze.
Dennis,
1
@Dennis Myślałem, że XOR będzie działać, aby usunąć już ustawioną flagę. notification.sound ^= Notification.DEFAULT_SOUND;
likejudo
3
Jak włączyć Walk? Ponieważ X | 0 == X
Unikorn
Jak wskazuje @Unikorn, wartość flagi równa zero nie działa poprawnie, albo jeśli spróbujesz włączyć ją LUB, albo jeśli spróbujesz ją wyłączyć.
RenniePet
Aby włączyć chodzenie, wystarczy wyłączyć bieg (co pozostawi bit 1 ustawiony na 0). Nie myśl o flagach ENABLE_ * jako o liczbach dziesiętnych, ale jako o liczbach binarnych, włączonych lub wyłączonych. Nadal nie możesz jednak jawnie włączyć ani wyłączyć chodzenia.
Jacob Degeling
82
my.emask &= ~(ENABLE_SHOOT);

aby wyczyścić kilka flag:

my.emask &= ~(ENABLE_SHOOT|SOME_OTHER|ONE_MORE);
Ned Batchelder
źródło
13

Należy zauważyć, że jeśli przetwarzana zmienna jest większa niż liczba int, wartość użyta w wyrażeniu „and not” również musi być. Właściwie czasami można uciec od używania mniejszych typów, ale jest wystarczająco dużo dziwnych przypadków, że prawdopodobnie najlepiej jest użyć sufiksów typów, aby upewnić się, że stałe są wystarczająco duże.

superkat
źródło
5
+1 za złapanie nieoczywistego narożnika. Jednym ze sposobów uniknięcia tego jest użycie flags -= flags & MY_FLAG;(lub ^=jeśli wolisz).
R .. GitHub STOP HELPING ICE
1
@R .. Użyłbym '^ =' z wyjątkiem tego, że będzie to przełączać bity i czasami możesz nie wiedzieć, która z wielu flag jest ustawiona. Jeśli chcę się upewnić, że dwa najbardziej prawe bity są równe zero, np. Moja.maska: '0 1 0 1' input: '0 0 1 1' with: '^ =' '0 1 1 0' with: '& ~ '0 1 0 0'
Hector