逻辑运算符(|| 和 &&)与位运算符(| 和 &)。
逻辑运算符和位运算符之间最重要的区别在于逻辑运算符采用两个布尔值并产生一个布尔值,而位运算符采用两个整数并产生一个整数 (注意:整数表示任何整数数据类型,而不仅仅是 int)。
为了迂腐,按位运算符采用位模式(例如 01101011)并对每个位进行按位与/或。因此,例如,如果您有两个 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
其次,通常可以对 bool 使用按位运算符,因为 true 和 false 分别相当于 1 和 0,如果将 true 转换为 1,将 false 转换为 0,则进行按位运算,然后转换非零到真,零到假;如果您刚刚使用逻辑运算符,结果将是相同的(检查此以进行练习)。
另一个重要的区别是逻辑运算符是短路的。因此,在某些圈子[1] 中,您经常会看到人们这样做:
if (person && person.punch()) {
person.doVictoryDance()
}
翻译为:“如果人存在(即不为空),尝试打他/她,如果打成功(即返回真),则跳胜利舞”。
如果您改用位运算符,则:
if (person & person.punch()) {
person.doVictoryDance()
}
将转换为:“如果 person 存在(即不为 null)并且出拳成功(即返回 true),则进行胜利之舞”。
请注意,在短路逻辑运算符中,如果person 为空,则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 文件系统权限中使用位模式和按位运算符的经典示例。