論理演算子(||
および&&
)とビット単位演算子(|
および&
)。
論理演算子とビット演算子の最も重要な違いは、論理演算子が2つのブール値を取得してブール値を生成するのに対し、ビット演算子は2つの整数を取得して整数値を生成することです(注:整数は整数だけでなく整数データ型を意味します)。
わかりやすくするために、ビットごとの演算子はビットパターン(たとえば、01101011)を取り、各ビットに対してビットごとのAND / ORを実行します。したがって、たとえば、2つの8ビット整数があるとします。
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)
論理演算子は以下でのみ機能しbool
ます。
a = true
b = false
--------------
a && b = false
a || b = true
2番目に、trueとfalseはそれぞれ1と0に相当するため、boolでビットごとの演算子を使用することがよくあります。trueを1に、falseを0に変換すると、ビットごとの演算が行われ、ゼロ以外の値に変換されます。真からゼロ、偽から 論理演算子を使用した場合と同じ結果になることがあります(これを確認してください)。
もう1つの重要な違いは、論理演算子が短絡していることです。したがって、一部のサークル[1]では、人々がこのようなことをしているのをよく見ます:
if (person && person.punch()) {
person.doVictoryDance()
}
これは、「人が存在する場合(つまり、nullでない場合)、パンチすることを試み、パンチが成功した場合(つまり、trueを返す)、勝利のダンスを行う」に変換されます。
代わりにビットごとの演算子を使用した場合、これは次のとおりです。
if (person & person.punch()) {
person.doVictoryDance()
}
「人が存在し(つまり、nullではない)、パンチが成功した(つまり、trueを返す)場合は、勝利のダンスを行います」に変換されます。
短絡論理演算子では、nullのperson.punch()
場合、コードがまったく実行されない可能性があることに注意してくださいperson
。場合、実際には、この特定の場合において、第二のコードはヌル参照エラーを生成するperson
ヌルであるが呼び出さないしようとするので、person.punch()
人がヌルであるか否かに関係なく。正しいオペランドを評価しないこの動作は、短絡と呼ばれます。
[1]一部のプログラマーは、副作用のある関数呼び出しをif
式の内部に置くことを非難し、他のプログラマーは一般的で非常に便利なイディオムです。
ビットワイズ演算子は一度に32ビットで動作するため(32ビットマシンを使用している場合)、膨大な数の条件を比較する必要がある場合、よりエレガントで高速なコードにつながる可能性があります。
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`
論理演算子を使用して同じことを行うと、厄介な量の比較が必要になります。
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;
ビットパターンとビットごとの演算子が使用される古典的な例は、Unix / Linuxファイルシステムのアクセス許可です。