Bit-OR o aggiunta di flag


16

Ho visto altri usare Bitwise-OR per combinare flag prima:

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

const byte madPerson = RUN | JUMP | SHOOT;

Questo è anche il modo in cui lo faccio.

Ma ho anche visto alcuni (non così tanti) combinare flag usando l'aggiunta:

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

const byte madPerson = RUN + JUMP + SHOOT;

Quale è più "leggibile"? (Quale pensi che riconosceranno più persone?) Qual è il modo "standard" per farlo? Quale preferisci?


Questa è una domanda SO. Considerare l'utilizzo di qualcosa di simile 1<<0, 1<<1, 1<<2, e così via. Quando hai molte bandiere, diventa più leggibile, più gestibile, meno soggetto a errori. Ad esempio, se stai impacchettando tutti i 64 bit di un int a 64 bit, vuoi davvero evitare errori di battitura :) Anche il modo in cui rappresenti 1è importante. Per un numero intero a 64 bit in VS2010 penso che sia 1UI64, o qualcosa del genere. L'uso di un tipo sbagliato potrebbe morderti.
Giobbe

3
@Job: non è una domanda StackOverflow, perché si chiede leggibilità, riconoscibilità, preferenze e best practice. Nessuna risposta obiettiva per questo; appartiene qui.
Macneil,

Risposte:


34

Bitwise-OR.

L'aggiunta è pericolosa.

Considera un esempio in cui un bandito è una persona e un bandito arrabbiato è un bandito che parla e spara. Successivamente, decidi che tutti i banditi dovrebbero sparare, ma ti sei dimenticato della definizione di bandito arrabbiato e non rimuovere la sua bandiera di tiro.

#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

Se avessi usato il angryBandit_addtuo gioco ora avrebbe l'errore di logica sconcertante di avere banditi arrabbiati che non possono sparare o essere uccisi.

Se avessi usato angryBandit_oril peggio che avresti è un ridondante | SHOOTS.

Per motivi simili, NOT bit a bit è più sicuro della sottrazione per la rimozione di flag.


11

bit-OR trasmette l'intento più chiaramente

inoltre, OR bit a bit dovrebbe essere più efficiente


+1 in effetti penso anche che OR renda più chiaro che si tratta di flag, ma per quanto riguarda l'efficienza ci sono lingue in cui le operazioni bit per bit sono lente, ad es. JavaScript tutti i numeri sono 64 float Gli operatori bit per bit devono fare una conversione implicita su quelli.
Ivo Wetzel,

1
Dato l'esempio del PO, non credo che una riga di OR o aggiunte avrà un impatto negativo sulla velocità di esecuzione di un programma.
Tin Man il

1
@Greg: soprattutto dal momento che il calcolo in quell'esempio verrà eseguito in fase di compilazione. :-)
Carson63000,

Oltre a trasmettere l'intento è abbastanza comune vederlo in molte lingue, tra cui ADA, C #, Java ...
Ken Henderson,

2
"dovrebbe" è una parola molto grande in questo settore. Mentre è altamente improbabile che tu possa riscontrare questo problema oggi, ho ricordi molto chiari di lavoro su un processore che non aveva un'istruzione bit-OR. È possibile bit-AND in una istruzione e bit-XOR in una istruzione, ma bit-OR ne prende due: un bit-bit immediato per disattivare il bit e un bit-XOR immediato per completare il bit appena cancellato , che ovviamente lo ha impostato.
John R. Strohm,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.