🔷 第三章 运算符与表达式
📄 一句话概括

第三章解决的是同一个问题:怎么把数据加工起来。三块拼图——九类运算符(3.1:算/比/管/问/选/排 + 位与移位)、优先级与结合性(3.2:谁先算)、表达式(3.3~3.4:组装、类型转换、左值右值)。第二章给了数据,这一章给了动作;下一章 if 让程序第一次"自己做决定"。

一、本章知识地图

块 小节 一句话要点
运算符 3.1 九类总览:算出数值·比出真假·管住内存·问出信息
3.1.1 + - * / %;整数除法丢小数;% 只认整数、符号跟被除数
3.1.2 六个比较符出 bool;== 与 = 手滑;浮点比相等用差值
3.1.3 && \|\| !;短路求值防除零;a<b<c 是错的
3.1.4 = 从右往左;+= 家族;连等号靠"赋值有值"
3.1.5 & \| ^ ~ 按位算;&=串联、|=并联;掩码筛位
3.1.6 << n = ×2ⁿ、>> n = ÷2ⁿ;左移补 0、右移补符号位
3.1.7 sizeof 量字节、编译期出结果;vs strlen:容量 vs 存量
3.1.8 ? : 三目、整个式子是值;只放值不放动作
3.1.9 逗号排队取末值;认得就行、别滥用
优先级 3.2 算术>移位>关系>逻辑>赋值>逗号;同级看结合性;记不清就加括号
表达式 3.3 表达式 = 运算符+操作数,必有值和类型
3.3.1 表达式(面粉)加分号成语句(面包);a+b; 白算
3.3.2 算术看最高、赋值看左边;转换位置决定成败((double)a/b ≠ (double)(a/b))
3.4 左值=有地址的盒子、右值=气球;= 左边必须左值

二、必须记住的五个结论

  1. == 问相等、= 装盒子——手滑写法 if (a = 5) 是"偷偷赋值再判真假",防手滑神技:常量放左边(5 == a)
  2. 整数除法丢小数,且是"砍"不是"舍"——7/2=3、-7/2=-3;想保小数,转换要在除法之前:(double)a / b
  3. 短路求值是安全带——n != 0 && 100/n > 10 防除零;防炸条件写左边
  4. 优先级抓大放小——背一句"算术>移位>关系>逻辑>赋值>逗号",其余全靠加括号
  5. 每个表达式有值有类型——类型转换"楼梯只上不下"(算术向上、赋值向左截);左值有地址、右值是气球

三、动手 Demo:两关自测

第一关(写程序):做一个"秒数分解器"——输入总秒数,输出几小时几分几秒,并判断秒数是奇还是偶。

#include <iostream>
using namespace std;

int main() {
    int total;
    cout << "请输入总秒数:";
    cin >> total;

    int h = total / 3600;          // 整数除法:小时
    int m = total % 3600 / 60;     // 去掉小时后取分
    int s = total % 60;            // 取秒
    cout << h << "小时" << m << "分" << s << "秒" << endl;
    cout << (total % 2 == 0 ? "偶数秒" : "奇数秒") << endl;
    return 0;
}

看到什么算成功:输入 7385,输出 2小时3分5秒 和 奇数秒。卡住的地方回看:拆位思路回 3.1.1、三目回 3.1.8、运算顺序回 3.2(total % 3600 / 60 为什么从左到右)。

第二关(找错):下面这段有五处问题,分别在哪?

#include <iostream>
using namespace std

int main() {
    int a = 7, b = 2;
    double avg = a / b;
    if (a = b)
        cout << "相等";
    cout << 5 > 3;
    return 0;
}

答案(五处):

  1. using namespace std 缺分号
  2. double avg = a / b; —— 整数除法先做完,avg 得 3.0 不是 3.5;应写 (double)a / b
  3. if (a = b) —— == 手滑成 =,把 a 改成 2 且条件恒假(2 非 0 即真?不对——b 是 2,非 0 即真,恒走"相等");应为 if (a == b)
  4. cout << 5 > 3; —— << 优先级高于 >,被拆成 (cout<<5) > 3;应写 cout << (5 > 3);
  5. (暗藏第 6 处)a = b 已经把 a 改成 2——数据被污染,后续再用 a 都错。手滑的代价不止条件错

30 秒实验:把第二关的五处全改对,跑一遍,看输出 2.5(改对 avg 后)。

四、常见误区(本章汇总)

  1. "运算符学会了就行,优先级背下来"——背不出也不必背。混用加括号是一劳永逸的策略,资深程序员也这么干
  2. "编译通过 = 写对了"——本章出现四次了:if(a=5)、a+b;、int x=3.9、(double)(a/b) 全都不报错。警告要看、结果要验
  3. "类型转换是自动的所以不用想"——自动 ≠ 正确。转换发生的位置(除法前还是后)决定答案对错
  4. "位运算用不上"——判奇偶、造掩码、算 2 的幂,& 1、& 0xF、1 << 10 都是实战写法;至少要读得懂
自测五问(点开对答案) 1. `5 / 2`、`5 % 2`、`5.0 / 2` 各是多少?——`2`、`1`、`2.5`。 2. `n % 2 == 0` 和 `!(n & 1)` 都在判什么?——n 是偶数(两种写法等价)。 3. `a || b && c` 怎么结合?——`a || (b && c)`,`&&` 优先级高。 4. `(double)(7 / 2)` 和 `(double)7 / 2` 各是多少?——`3.0` 和 `3.5`(转换位置!)。 5. `x = 3` 里哪部分是左值?——只有 `x`(盒子);3 和整个表达式的值都是右值。

相关笔记