逻辑运算符(||
和&&
)与按位运算符(|
和&
)。
逻辑运算符和按位运算符之间最关键的区别是,逻辑运算符采用两个布尔值并产生一个布尔值,而按位运算符采用两个整数并产生一个整数(注意:整数表示任何整数数据类型,而不仅仅是int)。
要学究一点,按位运算符采用位模式(例如01101011)并对每个位进行按位AND / OR。因此,例如,如果您有两个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
其次,由于布尔值true和false分别等于1和0,因此通常可以在bool上使用按位运算符,并且碰巧如果将true转换为1并将false转换为0,则进行按位运算,然后转换为非零为真,零为假;碰巧,如果您只是使用逻辑运算符,结果将是相同的(请检查此内容以进行练习)。
另一个重要的区别还在于逻辑运算符是短路的。因此,在某些圈子[1]中,您经常看到人们在做这样的事情:
if (person && person.punch()) {
person.doVictoryDance()
}
意思是:“如果某人存在(即不为null),则尝试对他/她进行打孔,如果该打孔成功(即,返回true),则进行一次胜利舞蹈”。
如果您改用按位运算符,则:
if (person & person.punch()) {
person.doVictoryDance()
}
会翻译为:“如果人存在(即不为null),并且拳打成功(即返回true),则进行胜利舞蹈”。
请注意,在短路逻辑运算符中,person.punch()
如果person
为null ,则可能根本不会运行代码。实际上,在这种特殊情况下,如果第二代码person
为null,则它将产生一个null引用错误,因为person.punch()
无论person 是否为null,它都会尝试调用。这种不评估正确操作数的行为称为短路。
[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文件系统权限。