Comment puis-je supprimer un indicateur en C?

Réponses:

339

Réponse courte

Vous souhaitez effectuer une opération ET au niveau du bit sur la valeur actuelle avec une opération NON au niveau du bit de l' indicateur que vous souhaitez annuler . Un NOT au niveau du bit inverse chaque bit (c'est-à-dire 0 => 1, 1 => 0).

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

Longue réponse

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

Lorsque vous effectuez un ET au niveau du bit avec PAS au niveau du bit de la valeur que vous souhaitez annuler.

value = value & ~ENABLE_SHOOT // 00000001

vous faites réellement:

      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
la source
@Aaron: Je suis content que cela ait aidé. Au départ, j'ai eu du mal à comprendre les opérations au niveau du bit jusqu'à ce que quelqu'un prenne 10 minutes pour l'expliquer sur papier.
Dennis
1
@Dennis Je pensais que XOR travaillerait pour supprimer un indicateur déjà défini. notification.sound ^= Notification.DEFAULT_SOUND;
likejudo
3
Comment activer Walk? Depuis X | 0 == X
Unikorn
Comme le souligne @Unikorn, une valeur d'indicateur de zéro ne fonctionne pas correctement, que ce soit si vous essayez de OUI ou si vous essayez de OUI.
RenniePet
Pour activer la marche, il vous suffit de désactiver la course (ce qui laissera le bit 1 à 0). Ne considérez pas les indicateurs ENABLE_ * comme des nombres décimaux, mais comme des nombres binaires, activés ou désactivés. Cependant, vous ne pouvez toujours pas activer ou désactiver explicitement la marche.
Jacob Degeling
82
my.emask &= ~(ENABLE_SHOOT);

pour effacer quelques drapeaux:

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

Il est important de noter que si la variable manipulée est plus grande qu'un int, la valeur utilisée dans l'expression 'and not' doit l'être également. En fait, on peut parfois s'en tirer en utilisant des types plus petits, mais il y a suffisamment de cas étranges pour qu'il soit probablement préférable d'utiliser des suffixes de type pour s'assurer que les constantes sont suffisamment grandes.

supercat
la source
5
+1 pour attraper le cas d'angle non évident. Une façon de l'éviter est d'utiliser à la place flags -= flags & MY_FLAG;(ou ^=si vous préférez).
R .. GitHub STOP AIDER ICE
1
@R .. J'aurais utilisé '^ =' sauf que cela fera basculer les bits et que parfois vous ne savez peut-être pas lesquels des nombreux indicateurs sont définis. Si je veux m'assurer que les deux bits les plus à droite sont zéro, par exemple my.emask: '0 1 0 1' entrée: '0 0 1 1' avec: '^ =' '0 1 1 0' avec: '& ~ '' 0 1 0 0 '
Hector