一、关系运算符与关系表达式
关系运算用于比较两个值的大小,是逻辑运算中最基础的部分。C++ 提供的关系运算符按优先级从高到低排列如下:
< <= > >= == !=
其中,<、<=、>、>= 的优先级高于 == 和 !=。
用关系运算符将两个表达式连接起来,就构成关系表达式。关系表达式的结果类型为 bool,即 true 或 false。
示例:
a > b
c <= a + b
x + y == 3Code language: HTML, XML (xml)
注意:关系相等判断使用双等号 ==,不要与赋值运算符 = 混淆。例如 if (a = 5) 是将 5 赋给 a 并判断结果非零,而 if (a == 5) 才是判断 a 是否等于 5。
二、逻辑运算符
仅有关系比较不足以表达复杂的判断条件,还需要用逻辑运算符将多个关系表达式组合起来,构成逻辑表达式。逻辑运算只能用于布尔类型的值或表达式。
C++ 提供三种逻辑运算符:
| 运算符 | 名称 | 操作数个数 | 说明 |
|---|---|---|---|
| ! | 逻辑非 | 一元 | 对操作数取反,true 变 false,false 变 true |
| && | 逻辑与 | 二元 | 两个操作数都为 true 时结果为 true,否则为 false |
| || | 逻辑或 | 二元 | 两个操作数都为 false 时结果为 false,否则为 true |
优先级顺序:! 最高,&& 次之,|| 最低。
三、逻辑运算规则
逻辑非(!):
!true 结果为 false
!false 结果为 true
逻辑与(&&):
| 操作数1 | 操作数2 | 结果 |
|---|---|---|
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
逻辑或(||):
| 操作数1 | 操作数2 | 结果 |
|---|---|---|
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false |
四、短路求值特性
逻辑与和逻辑或具有短路求值(short-circuit evaluation)特性,这是需要重点理解的内容。
对于逻辑或(||):如果第一个操作数的值为 true,则整个表达式的结果已经确定为 true,不再计算第二个操作数。
对于逻辑与(&&):如果第一个操作数的值为 false,则整个表达式的结果已经确定为 false,不再计算第二个操作数。
示例一:逻辑或的短路
bool a = false;
int c = 10;
bool result1 = (a == true || ++c > 12);
cout << c << endl; // 输出 10Code language: JavaScript (javascript)
分析:a 的值为 false,所以 a == true 的结果为 false。对于 || 运算,第一个操作数为 false,还需要计算第二个操作数。++c > 12 中 c 先自增为 11,11 > 12 为 false。因此 result1 为 false,c 的值变为 11。
注意:原文中 cout << c << endl; 输出 10 的分析有误。实际上 a == true 为 false,|| 不会短路,第二个操作数 ++c > 12 会被执行,c 自增为 11。因此正确输出应为 11。
示例二:逻辑与的短路
bool a = false;
int d = 10;
bool result2 = (a == true && ++d > 12);
cout << d << endl; // 输出 10Code language: JavaScript (javascript)
分析:a == true 的结果为 false。对于 && 运算,第一个操作数为 false,整个表达式结果已确定为 false,不再计算第二个操作数 ++d > 12。因此 d 的值保持 10 不变,输出 10。
五、代码示例
以下代码演示了关系表达式、逻辑表达式以及短路求值的行为:
#include <iostream>
using namespace std;
int main()
{
int x = 5, y = 10, z = 15;
// 关系表达式
cout << "(x < y) = " << (x < y) << endl; // 输出 1 (true)
cout << "(x == y) = " << (x == y) << endl; // 输出 0 (false)
// 逻辑非
bool flag = true;
cout << "!flag = " << !flag << endl; // 输出 0 (false)
// 逻辑与
cout << "(x < y && y < z) = " << (x < y && y < z) << endl; // 输出 1 (true)
// 逻辑或
cout << "(x > y || y < z) = " << (x > y || y < z) << endl; // 输出 1 (true)
// 短路求值演示
int c = 10;
bool a = false;
bool r1 = (a == true || ++c > 12);
cout << "after || : c = " << c << endl; // 输出 11,因为 || 未短路,++c 执行
int d = 10;
bool r2 = (a == true && ++d > 12);
cout << "after && : d = " << d << endl; // 输出 10,因为 && 短路,++d 未执行
// 复合条件示例:判断年份是否为闰年
int year = 2024;
bool isLeap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
cout << year << " is leap year : " << isLeap << endl; // 输出 1 (true)
return 0;
}Code language: PHP (php)
六、小结
- 关系表达式用于比较两个值,结果为 bool 类型。注意区分 == 和 =。
- 逻辑运算符包括 !、&&、||,用于组合多个布尔值。
- 逻辑与和逻辑或具有短路求值特性:|| 在第一个操作数为 true 时跳过第二个操作数;&& 在第一个操作数为 false 时跳过第二个操作数。
- 短路求值可以避免不必要的计算,有时还能防止错误,如指针非空判断后再访问成员:(p != nullptr && p->value > 0)。
- 书写条件表达式时,应将计算成本低、容易为假(对于 &&)或容易为真(对于 ||)的子表达式放在前面,以提高效率。