Как я могу удалить флаг в C?

148

Есть переменная, которая содержит некоторые флаги, и я хочу удалить один из них. Но я не знаю, как это удалить.

Вот как я установил флаг.

my.emask |= ENABLE_SHOOT;
Аарон де Виндт
источник
6
Вы можете найти полезные ответы на вопрос SO "Как установить, очистить и переключить один бит в C" .
Скот

Ответы:

339

Короткий ответ

Вы хотите выполнить побитовую операцию И для текущего значения с побитовой операцией НЕ для флага, который хотите сбросить . Побитовое НЕ инвертирует каждый бит (то есть 0 => 1, 1 => 0).

flags = flags & ~MASK;или flags &= ~MASK;.

Длинный ответ

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

Когда вы выполняете побитовое И с побитовым НЕ значение, которое вы хотите сбросить.

value = value & ~ENABLE_SHOOT // 00000001

вы на самом деле делаете:

      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)
Деннис
источник
@ Аарон: Я рад, что это помогло. Сначала я с трудом понимал побитовые операции, пока кому-то не потребовалось 10 минут, чтобы объяснить это на бумаге.
Деннис
1
@ Денис Я думал, что XOR будет работать, чтобы удалить уже установленный флаг. notification.sound ^= Notification.DEFAULT_SOUND;
likejudo
3
Как включить Walk? Так как X | 0 == X
Unikorn
Как указывает @Unikorn, нулевое значение флага не работает должным образом, либо если вы пытаетесь включить его, либо отключить его.
RenniePet
Чтобы включить прогон, вам просто нужно отключить прогон (в результате бит 1 будет установлен в 0). Не думайте о флагах ENABLE_ * как о десятичных числах, а как о двоичных числах, включенных или выключенных. Вы все еще не можете явно включить или отключить прогулку.
Джейкоб Дегелинг
82
my.emask &= ~(ENABLE_SHOOT);

очистить несколько флагов:

my.emask &= ~(ENABLE_SHOOT|SOME_OTHER|ONE_MORE);
Нед Бэтчелдер
источник
13

Важно отметить, что если манипулируемая переменная больше, чем int, значение, используемое в выражении «а не», также должно быть. На самом деле, иногда можно избежать использования меньших типов, но есть достаточно странных случаев, когда, вероятно, лучше использовать суффиксы типов, чтобы убедиться, что константы достаточно велики.

Supercat
источник
5
+1 за ловлю неочевидного углового случая. Один из способов избежать этого - вместо этого использовать flags -= flags & MY_FLAG;(или, ^=если хотите).
R .. GitHub ОСТАНОВИТЬ ЛЬДА
1
@R .. Я бы использовал '^ =', за исключением того, что он будет переключать биты, и иногда вы можете не знать, какой из множества флагов установлен. Если я хочу убедиться, что два самых правых бита равны нулю, например, my.emask: '0 1 0 1' input: '0 0 1 1' with: '^ =' '0 1 1 0' with: '& ~ '' 0 1 0 0 '
Гектор