Bagaimana cara menghapus bendera di C?

Jawaban:

339

Jawaban singkat

Anda ingin melakukan operasi Bitwise AND pada nilai saat ini dengan operasi Bitwise NOT pada flag yang ingin Anda hapus . A Bitwise TIDAK membalikkan setiap bit (yaitu 0 => 1, 1 => 0).

flags = flags & ~MASK;atau flags &= ~MASK;.

Jawaban panjang

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

Ketika Anda melakukan Bitwise DAN dengan Bitwise BUKAN dari nilai yang Anda inginkan tidak disetel.

value = value & ~ENABLE_SHOOT // 00000001

Anda sebenarnya melakukan:

      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
sumber
@ Harun: Aku senang itu membantu. Saya awalnya kesulitan memahami operasi bitwise sampai seseorang membutuhkan waktu 10 menit untuk menjelaskannya di atas kertas.
Dennis
1
@ Dennis Saya pikir XOR akan bekerja untuk menghapus bendera yang sudah ditetapkan. notification.sound ^= Notification.DEFAULT_SOUND;
likejudo
3
Bagaimana Anda mengaktifkan Walk? Sejak X | 0 == X
Unikorn
Seperti yang ditunjukkan oleh @Unikorn, nilai bendera nol tidak berfungsi dengan baik, baik jika Anda mencoba ATAU atau mengaktifkannya.
RenniePet
Untuk mengaktifkan walk, Anda hanya perlu menonaktifkan run (yang akan membuat bit 1 set ke 0). Jangan menganggap bendera ENABLE_ * sebagai angka desimal, tetapi sebagai angka biner, baik hidup atau mati. Anda masih tidak dapat secara aktif mengaktifkan atau menonaktifkan berjalan.
Jacob Degeling
82
my.emask &= ~(ENABLE_SHOOT);

untuk menghapus beberapa flag:

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

Penting untuk dicatat bahwa jika variabel yang dimanipulasi lebih besar dari int, nilai yang digunakan dalam ekspresi 'dan bukan' juga harus. Sebenarnya, seseorang kadang-kadang bisa pergi dengan menggunakan tipe yang lebih kecil, tetapi ada cukup kasus aneh yang mungkin terbaik untuk menggunakan sufiks tipe untuk memastikan konstanta cukup besar.

supercat
sumber
5
+1 untuk menangkap kasing sudut yang tidak terlihat. Salah satu cara untuk menghindarinya adalah dengan menggunakan flags -= flags & MY_FLAG;(atau ^=jika Anda mau).
R .. GitHub BERHENTI MEMBANTU ICE
1
@ R .. Saya akan menggunakan '^ =' kecuali itu akan beralih bit dan kadang-kadang Anda mungkin tidak tahu mana dari banyak flag yang ditetapkan. Jika saya ingin memastikan dua bit paling kanan adalah nol, misalnya input my.emask: '0 1 0 1': '0 0 1 1' dengan: '^ =' '0 1 1 0' dengan: '& ~ '' 0 1 0 0 '
Hector