C++逻辑运算符 #
一、逻辑运算符概述 #
逻辑运算符用于组合或修改布尔表达式,返回布尔值。
1.1 运算符列表 #
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
&& |
逻辑与 | a && b |
两者都为true时为true |
|| |
逻辑或 | a || b |
任一为true时为true |
! |
逻辑非 | !a |
取反 |
1.2 基本使用 #
cpp
#include <iostream>
int main() {
bool a = true;
bool b = false;
std::cout << std::boolalpha;
std::cout << "a && b: " << (a && b) << std::endl; // false
std::cout << "a || b: " << (a || b) << std::endl; // true
std::cout << "!a: " << (!a) << std::endl; // false
std::cout << "!b: " << (!b) << std::endl; // true
return 0;
}
二、逻辑与运算符 && #
2.1 真值表 #
| a | b | a && b |
|---|---|---|
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
2.2 基本用法 #
cpp
int age = 25;
bool hasLicense = true;
// 检查是否可以开车
if (age >= 18 && hasLicense) {
std::cout << "可以开车" << std::endl;
}
2.3 多条件组合 #
cpp
int score = 85;
int attendance = 90;
// 检查是否获得奖学金
if (score >= 80 && attendance >= 80 && score <= 100) {
std::cout << "获得奖学金" << std::endl;
}
2.4 短路求值 #
cpp
// 短路求值:如果左边为false,右边不会执行
int x = 5;
if (x > 10 && ++x > 0) {
// 不会执行
}
// x仍然是5,因为++x没有执行
if (x > 0 && ++x > 0) {
// 会执行
}
// x变成6
2.5 安全检查 #
cpp
int* ptr = nullptr;
int size = 10;
// 安全访问数组
if (ptr != nullptr && size > 0) {
// 只有ptr不为空时才访问
std::cout << ptr[0] << std::endl;
}
// 常见模式:先检查指针,再使用
if (ptr && *ptr > 0) {
// 安全
}
三、逻辑或运算符 || #
3.1 真值表 #
| a | b | a || b |
|---|---|---|
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false |
3.2 基本用法 #
cpp
int day = 6; // 星期六
// 检查是否是周末
if (day == 6 || day == 7) {
std::cout << "周末" << std::endl;
}
3.3 多条件组合 #
cpp
char grade = 'A';
// 检查是否是优秀
if (grade == 'A' || grade == 'B') {
std::cout << "优秀" << std::endl;
}
3.4 短路求值 #
cpp
// 短路求值:如果左边为true,右边不会执行
int x = 5;
if (x > 0 || ++x > 0) {
// 会执行
}
// x仍然是5,因为++x没有执行
if (x < 0 || ++x > 0) {
// 会执行
}
// x变成6
3.5 默认值设置 #
cpp
int userInput = 0;
int defaultValue = 10;
// 使用用户输入或默认值
int value = userInput || defaultValue; // 如果userInput为0,使用defaultValue
// 更清晰的写法
int value = (userInput != 0) ? userInput : defaultValue;
四、逻辑非运算符 ! #
4.1 真值表 #
| a | !a |
|---|---|
| true | false |
| false | true |
4.2 基本用法 #
cpp
bool isLoggedIn = false;
if (!isLoggedIn) {
std::cout << "请先登录" << std::endl;
}
4.3 与比较运算符结合 #
cpp
int x = 10;
// 检查x不等于5
if (!(x == 5)) {
std::cout << "x不是5" << std::endl;
}
// 等价于
if (x != 5) {
std::cout << "x不是5" << std::endl;
}
4.4 检查空指针 #
cpp
int* ptr = nullptr;
// 使用!
if (!ptr) {
std::cout << "空指针" << std::endl;
}
// 等价于
if (ptr == nullptr) {
std::cout << "空指针" << std::endl;
}
4.5 双重否定 #
cpp
int x = 5;
// 双重否定:转换为布尔值
bool isNonZero = !!x; // true
// 等价于
bool isNonZero = (x != 0);
五、运算符优先级 #
5.1 逻辑运算符优先级 #
cpp
// 优先级:! > && > ||
bool a = true, b = false, c = true;
bool r1 = a || b && c; // 等价于 a || (b && c) = true || false = true
bool r2 = !a && b; // 等价于 (!a) && b = false && false = false
bool r3 = !a || b; // 等价于 (!a) || b = false || false = false
5.2 与其他运算符的关系 #
cpp
int x = 5, y = 10;
// 关系运算符优先级高于逻辑运算符
bool r1 = x > 0 && y > 0; // 等价于 (x > 0) && (y > 0)
bool r2 = x > 0 || y < 0; // 等价于 (x > 0) || (y < 0)
// 赋值运算符优先级最低
bool r3 = x > 0 && y = 10; // 错误!需要括号
bool r4 = x > 0 && (y = 10); // 正确但不推荐
5.3 优先级表 #
| 优先级 | 运算符 |
|---|---|
| 高 | ! |
| 关系运算符 | |
&& |
|
| 低 | || |
5.4 使用括号 #
cpp
// 不清晰
bool result = a || b && c || d;
// 清晰
bool result = a || (b && c) || d;
六、德摩根定律 #
6.1 定律内容 #
text
!(a && b) = !a || !b
!(a || b) = !a && !b
6.2 应用示例 #
cpp
int x = 5;
// 原始条件
if (!(x > 0 && x < 10)) {
std::cout << "x不在0到10之间" << std::endl;
}
// 应用德摩根定律
if (x <= 0 || x >= 10) {
std::cout << "x不在0到10之间" << std::endl;
}
6.3 复杂条件简化 #
cpp
// 复杂条件
if (!(a > 0 && b > 0 && c > 0)) {
// ...
}
// 简化后
if (a <= 0 || b <= 0 || c <= 0) {
// ...
}
七、实际应用 #
7.1 输入验证 #
cpp
int age;
std::cout << "请输入年龄: ";
std::cin >> age;
// 验证年龄范围
if (age >= 0 && age <= 120) {
std::cout << "有效年龄" << std::endl;
} else {
std::cout << "无效年龄" << std::endl;
}
7.2 权限检查 #
cpp
bool isAdmin = true;
bool hasPermission = false;
// 检查是否有权限
if (isAdmin || hasPermission) {
std::cout << "允许访问" << std::endl;
}
7.3 条件组合 #
cpp
int score = 85;
int attendance = 90;
bool isMember = true;
// 复杂条件
if ((score >= 80 && attendance >= 80) || isMember) {
std::cout << "获得奖励" << std::endl;
}
7.4 游戏状态检查 #
cpp
int health = 50;
int shield = 30;
bool isInvincible = false;
// 检查是否存活
if (health > 0 || shield > 0 || isInvincible) {
std::cout << "角色存活" << std::endl;
}
八、位运算符 vs 逻辑运算符 #
8.1 区别 #
cpp
// 逻辑运算符:返回布尔值,短路求值
bool a = true, b = false;
bool r1 = a && b; // false
bool r2 = a || b; // true
// 位运算符:对每一位进行运算,不短路
int x = 5, y = 3; // x = 0101, y = 0011
int r3 = x & y; // 0001 = 1
int r4 = x | y; // 0111 = 7
8.2 常见错误 #
cpp
int x = 5;
// 错误:使用位运算符
if (x & 1) { // 正确但容易混淆
std::cout << "奇数" << std::endl;
}
// 正确:使用逻辑运算符
if (x && 1) { // 不正确!应该是 x & 1 或 x % 2 != 0
std::cout << "奇数" << std::endl;
}
// 正确的奇偶判断
if (x % 2 != 0) {
std::cout << "奇数" << std::endl;
}
九、三元运算符与逻辑运算 #
9.1 替代简单if-else #
cpp
int x = 10;
// 使用if-else
std::string result1;
if (x > 0) {
result1 = "正数";
} else {
result1 = "非正数";
}
// 使用三元运算符
std::string result2 = (x > 0) ? "正数" : "非正数";
9.2 与逻辑运算符结合 #
cpp
int score = 75;
// 复杂条件
std::string grade = (score >= 90) ? "A" :
(score >= 80) ? "B" :
(score >= 70) ? "C" :
(score >= 60) ? "D" : "F";
十、最佳实践 #
10.1 使用括号明确优先级 #
cpp
// 不推荐
if (a || b && c)
// 推荐
if (a || (b && c))
10.2 利用短路求值 #
cpp
// 安全访问
if (ptr != nullptr && ptr->isValid()) {
// 安全
}
// 避免不必要的计算
if (simpleCondition || expensiveCondition()) {
// 如果simpleCondition为true,不会调用expensiveCondition()
}
10.3 避免复杂表达式 #
cpp
// 不推荐:过于复杂
if ((a && b) || (c && d) || (e && f)) {
// ...
}
// 推荐:分解为有意义的变量
bool condition1 = a && b;
bool condition2 = c && d;
bool condition3 = e && f;
if (condition1 || condition2 || condition3) {
// ...
}
10.4 使用有意义的变量名 #
cpp
// 不推荐
if (age >= 18 && age <= 65 && hasLicense && !hasAccident) {
// ...
}
// 推荐
bool isWorkingAge = age >= 18 && age <= 65;
bool canDrive = hasLicense && !hasAccident;
if (isWorkingAge && canDrive) {
// ...
}
十一、总结 #
逻辑运算符一览 #
| 运算符 | 名称 | 说明 |
|---|---|---|
&& |
逻辑与 | 两者都为true时为true |
|| |
逻辑或 | 任一为true时为true |
! |
逻辑非 | 取反 |
短路求值规则 #
| 运算符 | 短路条件 |
|---|---|
&& |
左边为false时,不计算右边 |
|| |
左边为true时,不计算右边 |
注意事项 #
- 注意运算符优先级
- 利用短路求值提高效率和安全
- 使用括号明确意图
- 避免过于复杂的表达式
- 区分
&/|和&&/||
下一步,让我们学习位运算符!
最后更新:2026-03-26