Bitwise-OR vs ajout d'indicateurs

16

J'ai déjà vu d'autres utiliser Bitwise-OR pour combiner des indicateurs avant:

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

const byte madPerson = RUN | JUMP | SHOOT;

C'est aussi ainsi que je le fais.

Mais j'ai également vu certains (moins nombreux) combiner des indicateurs en utilisant l'addition:

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

const byte madPerson = RUN + JUMP + SHOOT;

Lequel est le plus "lisible"? (Laquelle pensez-vous que plus de gens reconnaîtront?) Quelle est la façon "standard" de le faire? lequel préfères-tu?

Mateen Ulhaq
la source
C'est une question SO. Pensez à utiliser quelque chose comme 1<<0, 1<<1, 1<<2et ainsi de suite. Lorsque vous avez de nombreux indicateurs, il devient plus lisible, plus facile à entretenir, moins sujet aux erreurs. Par exemple, si vous emballez tous les 64 bits d'un entier 64 bits, vous voulez vraiment éviter les fautes de frappe :) La façon dont vous représentez 1est également importante. Pour un entier 64 bits dans VS2010, je pense que c'est le cas 1UI64, ou quelque chose comme ça. Utiliser un mauvais type pourrait vous mordre.
Job
3
@Job: Pas une question StackOverflow, car il s'agit de lisibilité, de reconnaissance, de préférences et de meilleures pratiques. Aucune réponse objective unique pour cela; il appartient ici.
Macneil

Réponses:

34

Bitwise-OR.

L'ajout est dangereux.

Prenons un exemple où un bandit est une personne et un bandit en colère est un bandit qui parle et tire. Plus tard, vous décidez que tous les bandits doivent tirer, mais vous avez oublié la définition du bandit en colère et ne supprimez pas son drapeau de tir.

#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

Si vous utilisiez angryBandit_addvotre jeu, vous auriez maintenant l'erreur logique perplexe d'avoir des bandits en colère qui ne peuvent pas tirer ou être tués.

Si vous avez utilisé angryBandit_orle pire que vous auriez, c'est une redondance | SHOOTS.

Pour des raisons similaires, NOT au niveau du bit est plus sûr que la soustraction pour supprimer les drapeaux.

doppelgreener
la source
11

bit-OR exprime plus clairement l'intention

également, OR au niveau du bit devrait être plus efficace

Steven A. Lowe
la source
+1 en effet, je pense également que OR indique plus clairement qu'il s'agit de drapeaux, mais en ce qui concerne l'efficacité, il existe des langages où les opérations au niveau du bit sont lentes, par exemple, JavaScript tous les nombres sont 64 flottants, les opérateurs au niveau du bit doivent effectuer une conversion implicite sur ceux-ci.
Ivo Wetzel
1
Étant donné l'exemple de l'OP, je ne pense pas qu'une ligne de blocs opératoires ou d'addition aura un impact négatif sur la vitesse d'exécution d'un programme.
The Tin Man
1
@Greg: d'autant plus que le calcul dans cet exemple se fera au moment de la compilation. :-)
Carson63000
En plus de transmettre l'intention, il est assez courant de voir cela dans de nombreux langages, notamment ADA, C #, Java ...
Ken Henderson
2
"devrait" est un très grand mot dans cette entreprise. Bien qu'il soit très peu probable que vous rencontriez ce problème aujourd'hui, j'ai des souvenirs très clairs de travailler sur un processeur qui n'avait pas d'instruction OR au niveau du bit. Vous pourriez bitwise-ET dans une instruction, et vous pourriez bitwise-XOR dans une instruction, mais bitwise-OR en prend deux: un bitwise-AND immédiat pour désactiver le bit, et un bitwise-XOR immédiat pour compléter le bit nouvellement effacé , ce qui bien sûr l'a défini.
John R. Strohm