Bitwise-OR vs Menambahkan Bendera

16

Saya telah melihat orang lain menggunakan Bitwise-OR untuk menggabungkan flag sebelumnya:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN | JUMP | SHOOT;

Itu juga cara saya melakukannya.

Tapi saya juga melihat beberapa (tidak banyak) menggabungkan flag menggunakan tambahan:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN + JUMP + SHOOT;

Mana yang lebih "dapat dibaca"? (Menurut Anda, mana yang akan dikenali lebih banyak orang?) Apa cara "standar" untuk melakukannya? Yang mana yang Anda sukai?

Mateen Ulhaq
sumber
Ini pertanyaan SO. Pertimbangkan untuk menggunakan sesuatu seperti 1<<0, 1<<1, 1<<2, dan sebagainya. Ketika Anda memiliki banyak flag, itu menjadi lebih mudah dibaca, lebih dapat dipelihara, lebih sedikit rawan kesalahan. Misalnya, jika Anda mengemas semua 64 bit int 64 bit, Anda benar-benar ingin menghindari kesalahan ketik :) Cara Anda mewakili 1juga penting. Untuk integer 64 bit di VS2010 saya pikir itu 1UI64, atau sesuatu seperti itu. Menggunakan jenis yang salah bisa menggigit Anda.
Ayub
3
@Job: Bukan pertanyaan StackOverflow, karena menanyakan tentang keterbacaan, pengenalan, preferensi, dan praktik terbaik. Tidak ada jawaban obyektif tunggal untuk itu; itu milik sini.
Macneil

Jawaban:

34

Bitwise-ATAU.

Selain itu berbahaya.

Pertimbangkan sebuah contoh di mana seorang bandit adalah seseorang, dan seorang bandit yang marah adalah seorang bandit yang berbicara dan menembak. Kemudian, Anda memutuskan semua bandit harus menembak, tetapi Anda lupa tentang definisi bandit yang marah dan tidak menghapus bendera penembakannya.

#define PERSON 1 << 0
#define SPEAKS 1 << 1
#define SHOOTS 1 << 2
#define INVINCIBLE 1 << 3
const byte bandit = PERSON | SHOOTS;                    // 00000101
const byte angryBandit_add = bandit + SPEAKS + SHOOTS;  // 00001011 error
const byte angryBandit_or = bandit | SPEAKS | SHOOTS;   // 00000111 ok

Jika Anda menggunakan angryBandit_addgim Anda sekarang akan memiliki kesalahan logika yang membingungkan karena memiliki bandit marah yang tidak bisa menembak atau dibunuh.

Jika Anda menggunakan angryBandit_oryang terburuk yang Anda miliki adalah berlebihan | SHOOTS.

Untuk alasan yang sama, bitwise TIDAK lebih aman daripada pengurangan untuk menghapus flag.

doppelgreener
sumber
11

bitwise-ATAU menyampaikan maksud lebih jelas

juga, bitwise-OR harus lebih efisien

Steven A. Lowe
sumber
+1 memang saya juga berpikir bahwa ATAU membuatnya lebih jelas bahwa itu adalah flag, tetapi mengenai efisiensi ada bahasa di mana operasi bitwise lambat, mis. JavaScript semua Angka adalah 64 floats, operator bitwise perlu melakukan konversi tersirat pada mereka.
Ivo Wetzel
1
Mengingat contoh OP, saya tidak berpikir satu baris OR atau penambahan akan berdampak buruk pada kecepatan eksekusi suatu program.
the Tin Man
1
@Reg: terutama karena perhitungan dalam contoh itu akan dilakukan pada waktu kompilasi. :-)
Carson63000
Selain menyampaikan maksud, cukup umum untuk melihat ini dalam banyak bahasa termasuk tetapi tidak terbatas pada ADA, C #, Java ...
Ken Henderson
2
"Harus" adalah kata yang sangat besar dalam bisnis ini. Meskipun sangat tidak mungkin bahwa Anda akan menghadapi masalah ini hari ini, saya memiliki ingatan yang sangat jelas bekerja pada prosesor yang tidak memiliki instruksi bitwise-OR. Anda bisa bitwise-DAN dalam satu instruksi, dan Anda bisa bitwise-XOR dalam satu instruksi, tetapi bitwise-ATAU mengambil dua: bitwise langsung-DAN untuk mematikan bit, dan bitwise langsung-XOR untuk melengkapi bit yang baru dibersihkan , yang tentu saja mengaturnya.
John R. Strohm