Opérateur logique ( ||
et &&
) vs opérateur binaire ( |
et &
).
La différence la plus cruciale entre un opérateur logique et un opérateur au niveau du bit est qu'un opérateur logique prend deux booléens et produit un booléen tandis qu'un opérateur au niveau du bit prend deux entiers et produit un entier (note: les entiers signifie tout type de données intégral, pas seulement int).
Pour être pédant, un opérateur au niveau du bit prend un modèle de bits (par exemple 01101011) et effectue un ET / OU au niveau du bit sur chaque bits. Ainsi, par exemple, si vous avez deux entiers 8 bits:
a = 00110010 (in decimal: 32+16+2 = 50)
b = 01010011 (in decimal: 64+ 16+2+1 = 83)
----------------
a & b = 00010010 (in decimal: 16+2 = 18)
a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)
alors qu'un opérateur logique ne fonctionne que dans bool
:
a = true
b = false
--------------
a && b = false
a || b = true
Deuxièmement, il est souvent possible d'utiliser un opérateur binaire sur booléen puisque vrai et faux équivalent respectivement à 1 et 0, et il arrive que si vous traduisez vrai en 1 et faux en 0, effectuez une opération binaire, puis convertissez une valeur non nulle à vrai et zéro à faux; il arrive que le résultat soit le même si vous venez d'utiliser l'opérateur logique (vérifiez ceci pour l'exercice).
Une autre distinction importante est également qu'un opérateur logique est court-circuité . Ainsi, dans certains cercles [1], vous voyez souvent des gens faire quelque chose comme ceci:
if (person && person.punch()) {
person.doVictoryDance()
}
ce qui se traduit par: "si la personne existe (c'est-à-dire qu'elle n'est pas nulle), essayez de la frapper, et si le coup de poing réussit (c'est-à-dire qu'elle retourne vrai), alors faites une danse de la victoire" .
Si vous aviez utilisé un opérateur au niveau du bit à la place, ceci:
if (person & person.punch()) {
person.doVictoryDance()
}
se traduira par: "si la personne existe (c'est-à-dire n'est pas nulle) et que le coup de poing réussit (c'est-à-dire retourne vrai), alors faire une danse de la victoire" .
Notez que dans l'opérateur logique court-circuité, le person.punch()
code peut ne pas être exécuté du tout s'il person
est nul. En fait, dans ce cas particulier, le deuxième code produirait une erreur de référence nulle s'il person
est nul, car il essaie d'appeler person.punch()
, que personne soit nul ou non. Ce comportement consistant à ne pas évaluer le bon opérande est appelé court-circuit .
[1] Certains programmeurs hésiteront à mettre un appel de fonction qui a un effet secondaire dans une if
expression, tandis que pour d'autres, c'est un idiome commun et très utile.
Puisqu'un opérateur au niveau du bit fonctionne sur 32 bits à la fois (si vous êtes sur une machine 32 bits), cela peut conduire à un code plus élégant et plus rapide si vous avez besoin de comparer un grand nombre de conditions, par exemple
int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3,
CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6;
Person person;
person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS;
Place bar;
bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK;
Place military;
military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT;
CurrentLocation cloc1, cloc2;
cloc1.usable_abilities = person_abilities & bar_rules;
cloc2.usable_abilities = person_abilities & military_rules;
// cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT`
// while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`
Faire de même avec les opérateurs logiques exigerait une quantité délicate de comparaisons:
Person person;
person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true;
person.can_shoot_cannons = false;
Place bar;
bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true;
bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false;
Place military;
military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true;
military.rules.can_drink = military.rules.can_talk = false;
CurrentLocation cloc1;
bool cloc1.usable_abilities.can_punch = bar.rules.can_punch && person.can_punch,
cloc1.usable_abilities.can_kick = bar.rules.can_kick && person.can_kick,
cloc1.usable_abilities.can_drink = bar.rules.can_drink && person.can_drink,
cloc1.usable_abilities.can_sit = bar.rules.can_sit && person.can_sit,
cloc1.usable_abilities.can_shoot_guns = bar.rules.can_shoot_guns && person.can_shoot_guns,
cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons
cloc1.usable_abilities.can_talk = bar.rules.can_talk && person.can_talk;
bool cloc2.usable_abilities.can_punch = military.rules.can_punch && person.can_punch,
cloc2.usable_abilities.can_kick = military.rules.can_kick && person.can_kick,
cloc2.usable_abilities.can_drink = military.rules.can_drink && person.can_drink,
cloc2.usable_abilities.can_sit = military.rules.can_sit && person.can_sit,
cloc2.usable_abilities.can_shoot_guns = military.rules.can_shoot_guns && person.can_shoot_guns,
cloc2.usable_abilities.can_talk = military.rules.can_talk && person.can_talk,
cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;
Un exemple classique où les modèles binaires et l'opérateur binaire sont utilisés est celui des permissions du système de fichiers Unix / Linux.