目录

开始:C++ 运算符介绍
1. 运算符分类概览
2. 语法与用法示例 (1)
3. 语法与用法示例 (2)
4. 语法与用法示例 (3)
5. 执行顺序与优先级
6. 练习与自测
总结与应用建议

C++ 运算符详解

交互式教学幻灯片

适用于中学生与信息学竞赛入门者

⌨️

使用方向键
切换幻灯片

🖱️

点击幻灯片
逐步展示内容

📋

使用左上角按钮
打开目录

🌞

使用右上角按钮
切换主题

点击幻灯片任意位置或按下 → 键继续...

1. 运算符分类概览

📊C++ 运算符主要分类

C++ 提供了丰富的运算符,用于执行各种操作。了解它们的分类有助于系统学习。

分类 常见运算符 简述
算术运算符 +, -, *, /, %, ++, -- 执行基本数学计算,如加减乘除、取余、自增自减。
🔍关系运算符 ==, !=, >, <, >=, <= 比较两个操作数的关系,结果为布尔值 (truefalse)。
🔄逻辑运算符 && (与), || (或), ! (非) 连接或修改布尔表达式,用于构建复杂的条件判断。
📝赋值运算符 =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= 将值赋给变量,或执行运算后再赋值(复合赋值)。
🔢位运算符 &, |, ^, ~, <<, >> 直接操作变量的二进制位,常用于底层编程或优化。
条件(三目)运算符 ? : 根据条件选择两个值中的一个,是 if-else 的简洁形式。
🔗其他运算符 ,(逗号), sizeof(), &(取地址), *(解引用), ()(函数调用), [](下标) 等 具有特定功能的运算符。

💡运算符应用场景

运算符是构成 C++ 表达式的基础,它们无处不在:

  • 数值计算:科学计算、数据分析、游戏物理引擎等。
  • 条件控制if 语句、while/for 循环的条件判断。
  • 状态管理:使用位运算管理多个布尔标志位。
  • 内存操作:使用 &* 操作指针。
  • 代码简化:使用复合赋值、条件运算符使代码更紧凑。

学习提示:理解每个运算符的功能、需要的操作数类型以及返回结果的类型是关键。

2. 语法与用法示例 (算术、关系、逻辑)

算术运算符示例

#include <bits/stdc++.h>

int main() {
    int a = 10, b = 4;

    cout << "a + b = " << (a + b) << endl;  // 输出: 14
    cout << "a - b = " << (a - b) << endl;  // 输出: 6
    cout << "a * b = " << (a * b) << endl;  // 输出: 40
    cout << "a / b = " << (a / b) << endl;  // 整数除法,输出: 2
    cout << "a % b = " << (a % b) << endl;  // 取模(余数),输出: 2

    int c = 5;
    cout << "c++ (后置): " << c++ << endl; // 先输出 5, 然后 c 变为 6
    cout << "c 当前值: " << c << endl;   // 输出: 6
    cout << "++c (前置): " << ++c << endl; // c 先变为 7, 然后输出 7

    double da = 10.0, db = 4.0;
    cout << "da / db = " << (da / db) << endl; // 浮点数除法,输出: 2.5
    return 0;
}

注意:整数除法 / 会舍弃小数部分。取模 % 运算通常用于整数。区分 前置++先将变量加1,再使用变量的值。 (++var) 与 后置++先使用变量当前的值,再将变量加1。 (var++)。

🔍关系与 🔄逻辑运算符示例

#include <bits/stdc++.h>

int main() {
    int x = 5, y = 10, z = 5;
    bool flag1 = true, flag2 = false;

    // 关系运算
    cout << boolalpha; // 让 bool 输出 true/false 而不是 1/0
    cout << "x == z: " << (x == z) << endl; // 输出: true
    cout << "x != y: " << (x != y) << endl; // 输出: true
    cout << "x < y: " << (x < y) << endl;  // 输出: true
    cout << "y >= z: " << (y >= z) << endl; // 输出: true

    // 逻辑运算
    cout << "flag1 && flag2: " << (flag1 && flag2) << endl; // 逻辑与, 输出: false
    cout << "flag1 || flag2: " << (flag1 || flag2) << endl; // 逻辑或, 输出: true
    cout << "!flag1: " << (!flag1) << endl;         // 逻辑非, 输出: false

    // 组合使用
    if ((x < y) && (x == z)) {
        cout << "条件满足!" << endl; // 会输出
    }

    // 短路求值示例
    int counter = 0;
    // 因为 flag2 为 false,&& 右侧的 ++counter 不会执行
    bool result_and = flag2 && (++counter > 0);
    cout << "After &&, counter = " << counter << endl; // 输出: 0

    // 因为 flag1 为 true,|| 右侧的 ++counter 不会执行
     bool result_or = flag1 || (++counter > 0);
    cout << "After ||, counter = " << counter << endl; // 输出: 0

    return 0;
}
短路求值 (Short-circuit evaluation) 逻辑与 (&&) 和逻辑或 (||) 具有短路特性。对于 `A && B`,如果 A 为 false,则 B 不会被计算。对于 `A || B`,如果 A 为 true,则 B 不会被计算。这对于避免不必要的计算或防止错误很有用(如检查指针非空后再访问成员)。

3. 语法与用法示例 (赋值、位运算)

📝赋值运算符示例

#include <bits/stdc++.h>

int main() {
    int score = 100; // 基本赋值

    score += 10;      // score = score + 10; score 现在是 110
    cout << "Score after += 10: " << score << endl;

    score -= 20;      // score = score - 20; score 现在是 90
    cout << "Score after -= 20: " << score << endl;

    score *= 2;       // score = score * 2; score 现在是 180
    cout << "Score after *= 2:  " << score << endl;

    score /= 3;       // score = score / 3; score 现在是 60
    cout << "Score after /= 3:  " << score << endl;

    score %= 7;       // score = score % 7; score 现在是 4 (60除以7余4)
    cout << "Score after %= 7:  " << score << endl;

    // 同样适用于位运算符
    int flags = 5; // 二进制 0101
    flags |= 2;      // flags = flags | 2 (0010); flags 现在是 7 (0111)
    cout << "Flags after |= 2:  " << flags << endl;

    return 0;
}

复合赋值运算符 (如 +=, -=) 是对应运算和赋值的简写形式,可以使代码更简洁。

🔢位运算符示例

#include <bits/stdc++.h>

int main() {
    unsigned char a = 5;  // 二进制: 0000 0101
    unsigned char b = 12; // 二进制: 0000 1100

    cout << "a      = " << bitset<8>(a) << " (" << (int)a << ")" << endl;
    cout << "b      = " << bitset<8>(b) << " (" << (int)b << ")" << endl;

    // 按位与 (&): 对应位都为1时,结果位才为1
    unsigned char result_and = a & b; // 0000 0100
    cout << "a & b  = " << bitset<8>(result_and) << " (" << (int)result_and << ")" << endl; // 输出 4

    // 按位或 (|): 对应位有一个为1时,结果位就为1
    unsigned char result_or = a | b;  // 0000 1101
    cout << "a | b  = " << bitset<8>(result_or) << " (" << (int)result_or << ")" << endl;  // 输出 13

    // 按位异或 (^): 对应位不同时,结果位为1;相同时为0
    unsigned char result_xor = a ^ b; // 0000 1001
    cout << "a ^ b  = " << bitset<8>(result_xor) << " (" << (int)result_xor << ")" << endl; // 输出 9

    // 按位非 (~): 对每一位取反 (0变1, 1变0)
    unsigned char result_not_a = ~a; // 1111 1010
    cout << "~a     = " << bitset<8>(result_not_a) << " (" << (int)result_not_a << ")" << endl; // 输出 250

    // 左移 (<<): 所有位向左移动指定位数,右侧补0
    unsigned char result_left_shift = a << 2; // 0001 0100
    cout << "a << 2 = " << bitset<8>(result_left_shift) << " (" << (int)result_left_shift << ")" << endl; // 输出 20 (相当于 5 * 2^2)

    // 右移 (>>): 所有位向右移动指定位数
    // 对于 unsigned 类型,左侧补0
    // 对于 signed 类型,行为可能依赖实现 (通常补符号位 - 算术右移)
    unsigned char result_right_shift = b >> 1; // 0000 0110
     cout << "b >> 1 = " << bitset<8>(result_right_shift) << " (" << (int)result_right_shift << ")" << endl; // 输出 6 (相当于 12 / 2^1)

    return 0;
}

应用场景:位运算常用于状态压缩用一个整数的不同位来表示多个布尔状态,节省空间。快速乘除2的幂左移 `<< n` 相当于乘以 2n,右移 `>> n` 相当于除以 2n (对正整数)。、掩码操作、权限管理、加解密算法等。

4. 语法与用法示例 (条件、逗号、其他)

条件(三目)运算符 ? :

条件运算符提供了一种基于条件选择两个值之一的简洁方式。

语法: condition ? value_if_true : value_if_false

#include <iostream>
#include <string>

int main() {
    int a = 10, b = 20;
    int maxValue;

    // 使用 if-else 找最大值
    if (a > b) {
        maxValue = a;
    } else {
        maxValue = b;
    }
    cout << "Max value (if-else): " << maxValue << endl; // 输出 20

    // 使用条件运算符实现相同功能
    maxValue = (a > b) ? a : b;
    cout << "Max value (ternary): " << maxValue << endl; // 输出 20

    // 也可以直接在输出中使用
    cout << "The smaller value is: " << ((a < b) ? a : b) << endl; // 输出 10

     // 根据分数判断等级
     int score = 85;
     string grade = (score >= 90) ? "优秀" : (score >= 60) ? "及格" : "不及格";
     cout << "成绩 " << score << " 对应的等级是: " << grade << endl; // 输出 及格

    return 0;
}

优点: 简洁。缺点: 嵌套过多会降低可读性。适合简单的条件赋值。

🔗逗号运算符 ,

逗号运算符用于连接两个或多个表达式。它会从左到右依次计算每个表达式,并返回最右侧表达式的值。

#include <iostream>

int main() {
    int a = 1, b = 2, c = 3, result;

    // 表达式1: a++, 表达式2: b++, 表达式3: c++
    result = (a++, b++, c++);

    // a, b, c 都会自增
    cout << "a = " << a << endl; // 输出: 2
    cout << "b = " << b << endl; // 输出: 3
    cout << "c = " << c << endl; // 输出: 4

    // result 的值等于最后一个表达式 (c++) 的值 *在自增之前* 的值
     cout << "result = " << result << endl; // 输出: 3

    // 常见于 for 循环的初始化和迭代表达式
    for (int i = 0, j = 10; i < j; i++, j--) {
        cout << "i=" << i << ", j=" << j << "  ";
    }
    cout << endl;
    // 输出: i=0, j=10  i=1, j=9  i=2, j=8  i=3, j=7  i=4, j=6

    return 0;
}

逗号运算符的优先级是最低的,需要注意括号的使用。

⚙️其他常用运算符

  • sizeof(type/variable): 返回类型或变量在内存中占用的字节数。
    cout << "Size of int: " << sizeof(int) << " bytes" << endl;
  • &variable (取地址): 返回变量的内存地址。
    int num = 10; int* ptr = &num;
  • *pointer (解引用): 访问指针指向地址的值。
    cout << "Value pointed by ptr: " << *ptr << endl; // 输出 10
  • () (函数调用): 调用函数。
    int result = myFunction(arg1, arg2);
  • [] (下标): 访问数组或容器元素。
    int arr[] = {1, 2, 3}; int second = arr[1]; // second is 2
  • . (成员访问): 访问对象或结构体的成员。
    myObject.memberVariable = 5;
  • -> (指针成员访问): 通过指针访问对象或结构体的成员 (等价于 (*ptr).member)。
    myPointer->memberFunction();

这些运算符在 C++ 编程中非常基础和重要。

5. 运算符执行顺序与优先级

🚦优先级 (Precedence)

当一个表达式包含多个不同运算符时,优先级决定了哪个运算符先执行。优先级高的运算符先于优先级低的运算符进行计算。

例如:在 a + b * c 中,乘法 * 的优先级高于加法 +,所以先计算 b * c,再计算 a + (b * c)

↔️结合性 (Associativity)

当一个表达式包含多个相同优先级的运算符时,结合性决定了它们的执行顺序是从左到右还是从右到左。

  • 左结合性 (Left-to-right): 大多数运算符是左结合的,如 a + b - c 等价于 (a + b) - c。算术、关系、逻辑与/或、位运算等都是左结合。
  • 右结合性 (Right-to-left): 少数运算符是右结合的,如赋值运算符 (a = b = c 等价于 a = (b = c))、一元运算符 (! ++ -- ~ * & 等,如 *ptr++ 会先执行 ++ 再解引用)、条件运算符 (a ? b : c ? d : e 等价于 a ? b : (c ? d : e))。

⛰️优先级金字塔 (简化版)

以下是常见运算符的优先级,从高到低排列(同一行优先级相近或相同):

最高作用域解析符 ::::
后缀/成员/调用后缀 ++ --, 函数调用 (), 下标 [], 成员访问 . ->() [] -> . ++ -- (后缀)
前缀/一元前缀 ++ --, 逻辑非 !, 按位非 ~, 正负号 +, -, 取地址&, 解引用*, sizeof, new, delete (右结合)++ -- ! ~ + - * & sizeof (前缀/一元)
乘除模乘 *, 除 /, 取模 % (左结合)* / %
加减加 +, 减 - (左结合)+ -
位移左移 <<, 右移 >> (左结合)<< >>
关系小于 <, 小于等于 <=, 大于 >, 大于等于 >= (左结合)< <= > >=
相等性等于 ==, 不等于 != (左结合)== !=
按位与按位与 & (左结合)& (按位与)
按位异或按位异或 ^ (左结合)^ (按位异或)
按位或按位或 | (左结合)| (按位或)
逻辑与逻辑与 && (左结合)&&
逻辑或逻辑或 || (左结合)||
条件(三目)条件运算符 ? : (右结合)?:
赋值赋值 =, 复合赋值 += -= *= 等 (右结合)= += -= *= /= %= &= ^= |= <<= >>=
最低逗号运算符 , (左结合),

最佳实践:不要过度依赖优先级规则!当表达式复杂或不确定时,使用括号 () 来明确指定计算顺序,这样可以大大提高代码的可读性并减少错误。

// 不清晰
int result = a + b << 2 & c;

// 清晰
int result_clear = ((a + b) << 2) & c;

6. 练习与自测

✏️练习 1: 表达式求值

假设 int a = 5, b = 3, c = 2;,请计算以下表达式的值:

1. a / c * b
2. a + b % c * a
3. (++a + b--) * c

注意:第3题会改变 a 和 b 的值。

解析:

  1. a / c * b => 5 / 2 * 3 (整数除法) => 2 * 3 => 6 (乘除优先级相同,左结合)
  2. a + b % c * a => 5 + 3 % 2 * 5 (取模和乘法优先级高于加法) => 5 + (3 % 2) * 5 => 5 + 1 * 5 => 5 + 5 => 10 (% 和 * 优先级相同,左结合)
  3. (++a + b--) * c:
    • ++a (前置自增): a 变为 6,表达式值为 6。
    • b-- (后置自减): 表达式值为 3,之后 b 变为 2。
    • (6 + 3) * c => 9 * 2 => 18
    • 执行后, a = 6, b = 2, c = 2

🧠练习 2: 逻辑与位运算判断

假设 int x = 10; (二进制 1010), int y = 6; (二进制 0110), bool p = true, q = false; 判断以下表达式的结果 (true/false 或 整数值):

1. (x > 1) == (y & 5) // 5 的二进制是 0101
2. p || !q && q
3. x ^ y | 3        // 3 的二进制是 0011

解析:

  1. (x >> 1) == (y & 5)
    • x >> 1: 1010 >> 1 => 0101 (十进制 5)
    • y & 5: 0110 & 0101 => 0100 (十进制 4)
    • 5 == 4 => false
  2. p || !q && q (! 优先级最高, 然后 &&, 最后 ||)
    • !q: !false => true
    • true && q: true && false => false
    • p || false: true || false => true
  3. x ^ y | 3 (^| 中, ^ 优先级略高)
    • x ^ y: 1010 ^ 0110 => 1100 (十进制 12)
    • 1100 | 0011 => 1111 (十进制 15)

✍️练习 3: 代码阅读理解

分析以下代码片段,执行后变量 a, b, result 的最终值是多少?

int a = 1, b = 2;
bool result = (--a == 0) && (b++ > 2);

解析:

这是一个利用逻辑与 && 短路特性的例子。

  1. 执行 --a (前置自减): a 从 1 变为 0,表达式 --a 的值为 0。
  2. 判断 (--a == 0): 即 0 == 0,结果为 true
  3. 因为 && 左侧为 true,需要继续计算右侧 (b++ > 2)
  4. 执行 b++ (后置自增): 表达式 b++ 的值为 b 当前的值 2。之后 b 变为 3。
  5. 判断 (b++ > 2): 即 2 > 2,结果为 false
  6. 整个逻辑与表达式为 true && false,结果为 false
  7. false 赋值给 result

最终结果:

  • a = 0
  • b = 3
  • result = false

总结与应用建议

知识点回顾

  • C++ 提供了多种运算符,包括算术、关系、逻辑、赋值、位、条件等。
  • 每个运算符有其特定的功能、操作数要求和返回类型。
  • 运算符的优先级结合性决定了复杂表达式的计算顺序。
  • 逻辑运算符 (&&, ||) 具有短路求值特性。
  • 位运算符直接操作二进制位,在特定场景下非常有用。

🚀应用建议

  • 熟练掌握:基础运算符是编程的基石,务必熟练掌握它们的用法。
  • 清晰优先:不要滥用复杂的运算符组合。当优先级不明确或表达式复杂时,果断使用括号 () 来明确意图,提高代码可读性。
  • 理解类型:注意不同类型参与运算可能发生的隐式类型转换,尤其是在整数和浮点数混合运算时。
  • 善用简写:合理使用复合赋值运算符 (+=, -= 等) 和条件运算符 (?:) 可以让代码更简洁,但前提是不牺牲可读性。
  • 巧用位运算:在需要进行状态管理、性能优化或处理底层数据时,考虑使用位运算符。但要确保自己和他人能理解代码逻辑。
  • 勤加练习:通过编写代码、解决问题来不断巩固对运算符的理解和应用。

🎉继续学习

运算符只是 C++ 语言的一部分。接下来你可以继续探索:

  • 控制流语句 (if, switch, for, while) 如何与运算符结合使用。
  • 函数和运算符如何协同工作。
  • 面向对象编程中的运算符重载。
  • 标准模板库 (STL) 中的算法和数据结构。

祝你在 C++ 的学习道路上不断进步!