Como posso remover um sinalizador em C?

Respostas:

339

Resposta curta

Você deseja executar uma operação Bitwise AND no valor atual com uma operação Bitwise NOT do sinalizador que deseja desarmar . Um Bitwise NOT inverte todos os bits (ou seja, 0 => 1, 1 => 0).

flags = flags & ~MASK;ou flags &= ~MASK;.

Resposta longa

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

Quando você executa um Bitwise AND com Bitwise NOT do valor que deseja desabilitar.

value = value & ~ENABLE_SHOOT // 00000001

você está realmente fazendo:

      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
fonte
@ Aaron: Estou feliz que ajudou. Inicialmente, tive problemas para entender as operações bit a bit até que alguém levou 10 minutos para explicá-lo no papel.
Dennis
1
@ Dennis, pensei que o XOR funcionaria para remover um sinalizador já definido. notification.sound ^= Notification.DEFAULT_SOUND;
Likejudo
3
Como você habilita o Walk? Desde o X | 0 == X
Unikorn 29/04
Como o @Unikorn aponta, um valor de flag zero não funciona corretamente, se você tentar ativá-lo ou ativá-lo.
RenniePet
Para ativar a caminhada, basta desabilitar a execução (que deixará o bit 1 definido como 0). Não pense nos sinalizadores ENABLE_ * como números decimais, mas como números binários, ativados ou desativados. No entanto, você ainda não pode habilitar ou desabilitar explicitamente a caminhada.
Jacob Degeling
82
my.emask &= ~(ENABLE_SHOOT);

para limpar algumas bandeiras:

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

É importante observar que, se a variável que está sendo manipulada for maior que um int, o valor usado na expressão 'e não' também deverá ser. Na verdade, às vezes é possível evitar o uso de tipos menores, mas há casos ímpares suficientes para que provavelmente seja melhor usar sufixos de tipo para garantir que as constantes sejam grandes o suficiente.

supercat
fonte
5
+1 para capturar a caixa de canto não óbvia. Uma maneira de evitá-lo é usar flags -= flags & MY_FLAG;(ou ^=se você preferir).
R .. GitHub Pare de ajudar o gelo
1
@R .. Eu teria usado '^ =', exceto que alternará os bits e, às vezes, você pode não saber qual dos muitos sinalizadores está definido. Se eu quiser ter certeza de que os dois bits mais corretos sejam zero, por exemplo, my.emask: '0 1 0 1' input: '0 0 1 1' com: '^ =' '0 1 1 0' com: '& ~ '' 0 1 0 0 '
Hector