# 第二章 程序的基本组成

> Arietids Learn · 个人课程复习笔记
> 在线阅读：https://learn.arietids.net/courses/programming/chapter-02/

## 关键考点总览

1. C++程序的三部分结构（注释、环境设置、主程序）
2. 程序注释的两种写法（`//` 和 `/* */`）
3. 库包含格式（`<>` 系统库 vs `""` 用户库）
4. 名字空间的作用与使用（`using namespace std;`）
5. 变量定义格式、命名规则、初始化方式
6. 基本数据类型（整型、实型、字符型、布尔型、枚举）及表示范围
7. 整型的三种码制（原码、反码、补码）
8. `cin`/`cout` 的使用及格式化输入输出
9. 算术运算符、优先级、类型转换规则
10. 强制类型转换与自增自减运算符

---

## 详细知识点

### 2.1 程序实例

#### 定义/语法

- **C++程序的基本组成**分为三部分：
  1. **程序注释**：描述程序操作过程的说明
  2. **环境设置**：预处理命令 + 名字空间声明
  3. **主程序**：程序要执行的命令序列
  
  [来源：第2章 p5，C++程序的基本组成]

- **Hello World 程序结构**：
  ```cpp
  // 程序注释
  #include <iostream>    // 预处理命令
  using namespace std;   // 名字空间
  
  int main(){            // 主程序
      cout << "hello world!" << endl;
      return 0;
  }
  ```
  [来源：第2章 p5]

#### 规则/规范

- 大多数**语句（statement）**以分号 `;` 结束，但**预处理指令**（如 `#include`）、**复合语句/语句块**（`{}`）、以及控制结构（如 `if/for/while` 后接 `{}`）等**不以分号结尾**；另外 `class/struct/enum` 的**声明末尾需要分号**。
  [来源：第2章 p5，Notes]

- 每个程序**必须有一个名为 `main` 的函数**，它是程序的入口
  [来源：第2章 p11，主程序]

- 在常见的**宿主环境（hosted）**下，一个**可执行程序整体**必须且只能有一个 `main` 作为入口（多文件工程中也只能在某一个源文件里定义一次）；在某些**裸机/嵌入式（freestanding）**环境下标准不强制必须有 `main`。
  [来源：第2章 p11，Notes]

---

### 2.2 程序注释

#### 定义/语法

- **程序注释**：描述程序操作过程的说明，会被编译器忽略
  [来源：第2章 p6，程序注释]

- **两种注释方式**：
  1. **单行注释**：从 `//` 开始到本行结束
  2. **多行注释**：`/*` 与 `*/` 之间的所有文字，可跨行
  
  [来源：第2章 p6]

#### 规则/规范

- 注释可以出现在程序的**任何位置**
  [来源：第2章 p6]

- `/* */` 方式**不能嵌套**使用
  [来源：第2章 p6，Notes]

- **良好的注释习惯**：
  - 每个程序文件顶端：说明程序文件的功能
  - 每个程序模块：说明功能、输入输出变量
  - 难以理解的地方：及时添加说明
  
  [来源：第2章 p6，Notes]

---

### 2.3 编译预处理

#### 定义/语法

- **预处理命令**的主要功能：
  1. **库包含**：使用其他地方定义好的功能模块
  2. **宏定义**：定义符号常量或复杂操作
  
  [来源：第2章 p7，编译预处理]

- **库包含格式**：
  ```cpp
  #include <filename>   // 通常用于：按**系统/配置的包含路径**搜索头文件
  #include "filename"   // 通常用于：先按**当前/项目路径**搜索，再按系统包含路径搜索
  ```
  [来源：第2章 p8，库包含的格式]

- **宏定义格式**：
  ```cpp
  #define 标识符 替换文本
  // 例如：
  #define RADIUS 5
  #define PI 3.14159
  #define AREA (PI*(RADIUS)*(RADIUS))   // 宏替换建议加括号，避免优先级问题
  ```
  [来源：第2章 p9，宏定义]

#### 规则/规范

- **库（头文件）**在预处理时被放入源代码中，用于对库调用做初步检查
  [来源：第2章 p8，Notes]

#### 易错点与辨析

- ⚠️ **宏定义的缺点**：
  1. 编译器不会对宏进行**类型检测**，程序容易出错
  2. 每个使用部分会被**简单替换**，造成代码膨胀
  
  [来源：第2章 p9，宏定义]

- **C++更好的方案**：用 `const` 定义全局常量
  ```cpp
  const double PI = 3.14159;
  ```
  [来源：第2章 p9]

---

### 2.4 名字空间

#### 定义/语法

- **名字空间**：由一组程序实体组合成的一个作用域
  [来源：第2章 p10，名字空间]

- **格式**：
  ```cpp
  using namespace 名字空间名;
  ```
  [来源：第2章 p10]

#### 规则/规范

- **用于解决多人开发时的重名问题**：
  - 同一名字空间中的实体**不能重名**
  - 不同名字空间中**可以定义相同的实体名**
  
  [来源：第2章 p10]

- 跨名字空间调用时，需用**限定符 `::`**：
  ```cpp
  std::cout << "hello world!" << endl;
  ```
  [来源：第2章 p10]

- C++标准库中的实体都定义在 **`std`** 名字空间中
  [来源：第2章 p10]

---

### 2.5 主程序（main函数）

#### 定义/语法

- **函数头**：`int main()`
  - `int`：函数返回结果的数据类型
  - `main`：函数名
  - `()`：函数输入变量（空表示不需要输入）
  
  [来源：第2章 p11，Notes]

- **函数体**：用大括号 `{}` 括起来的命令序列
  [来源：第2章 p11]

---

### 2.6 变量定义

#### 定义/语法

- **变量**：存放可变数据的空间
  [来源：第2章 p15，变量定义]

- **变量的三个重要属性**：类型、名称、值
  [来源：第2章 p15]

- **变量定义格式**：
  ```cpp
  类型名 变量名1, 变量名2, ..., 变量名n;
  // 例如：
  int num1, num2;      // 定义两个int类型变量
  double area;         // 定义一个double型变量
  ```
  [来源：第2章 p15]

#### 规则/规范

- 在C++中，**每个变量在使用前必须被定义**，以便编译器检查变量使用的合法性
  [来源：第2章 p15]

---

### 2.7 变量命名

#### 规则/规范

- **强制规则**：
  1. 必须以**字母或下划线**开头
  2. 其他字符必须是**字母、数字或下划线**
  3. **不得使用空格或其他特殊符号**
  4. **大写和小写字母被看作不同字符**（`ABC`、`Abc`、`abc` 是三个不同名字）
  5. 不可以是**系统保留词**（如 `int`, `double`, `for`, `return` 等）
  
  [来源：第2章 p16，变量命名]

- **习惯约定**：起名应使读者易于明白其用途，做到"**见名知意**"
  - 常用缩写：`number` → `num`，`function` → `func`，`Number of dimensions` → `num_dims` / `nDims`
  
  [来源：第2章 p16]

---

### 2.8 变量初始化

#### 定义/语法

- **两种初始化格式**：
  ```cpp
  类型名 变量名 = 数值;    // 等号赋值
  类型名 变量名(数值);     // 括号赋值
  
  // 例如：
  int count = 0;           // 或 int count(0);
  int sum = 0, count = 0, num;  // 部分变量赋初值
  ```
  [来源：第2章 p17，变量初始化]

#### 易错点与辨析

- ⚠️ **使用未初始化变量有危险！** 对于函数内的**局部自动变量**（非 `static`），定义后若不显式初始化，其值通常**不确定**；但**全局变量/静态存储期变量**（如全局变量、`static` 局部变量）会被**零初始化**。
  [来源：第2章 p17]

---

### 2.9 数据类型

#### 定义/语法

- **数据类型的作用**：定规则
  1. 怎么把二进制数翻译成各种字母、数字、特殊符号
  2. 怎么对变量进行计算上的操作
  
  [来源：第2章 p18，数据类型]

- **数据类型种类**：
  1. **基本类型（内置类型）**
  2. **自定义类型**
  
  [来源：第2章 p18]

- **基本类型分类**：

| 大类 | 具体类型 |
|------|----------|
| 整型 | `int`, `short`, `long`, `unsigned int`, `unsigned short`, `unsigned long` |
| 实型 | `float`, `double`, `long double` |
| 字符型 | `char` |
| 布尔型 | `bool` |

[来源：第2章 p18]

---

### 2.10 整型

#### 定义/语法

- **整型占用内存与表示范围**（与平台/编译器/ABI 有关，标准只规定下限；可用 `sizeof`/`numeric_limits` 实测）：

| 类型 | 标准保证（至少） | 常见实现举例（仅供参考） |
|------|------------------|--------------------------|
| `short` | ≥ 16 位 | 常见：2 字节 |
| `int` | ≥ `short`，且 ≥ 16 位 | 常见：4 字节 |
| `long` | ≥ 32 位，且 ≥ `int` | Windows 64 位常见：4 字节（LLP64）；Linux/macOS 64 位常见：8 字节（LP64） |
| `long long` | ≥ 64 位 | 常见：8 字节 |

- **无符号整数**：范围为 `0 ~ (2^N - 1)`，其中 `N` 为对应类型的位数（例如 `unsigned int` 若为 32 位则为 `0~2^32-1`；若为 16 位则为 `0~2^16-1`）。

[来源：第2章 p20]

#### 规则/规范

- **整数支持的运算**：
  - 算术运算：`++`, `--`, `-`（负号）, `*`, `/`, `%`, `+`, `-`
  - 逻辑运算：`&&`, `||`, `!`
  - 关系运算：`>`, `<`, `==`, `>=`, `<=`, `!=`
  
  [来源：第2章 p21，整型数的运算]

#### 易错点与辨析

- ⚠️ **整数溢出/越界**：在 C++ 中，**有符号整型**发生溢出属于**未定义行为**（不能依赖“会回绕成 -32768”这类结果）；而**无符号整型**溢出是**按模 `2^N` 回绕**（语言有明确定义）。编译器通常也不会主动提示，需要程序员避免或显式处理。
  
  [来源：第2章 p21]

---

### 2.11 整型数的码制

#### 定义/语法

- **符号位数字化**：0表示正数，1表示负数
  [来源：第2章 p22]

- **三种编码方式**（以一个字节为例）：

| 编码 | 定义 | +62 | -62 |
|------|------|-----|-----|
| **原码** | 符号位+数值的二进制 | `0 0111110` | `1 0111110` |
| **反码** | 正数同原码，负数=绝对值原码取反 | `0 0111110` | `1 1000001` |
| **补码** | 正数同原码，负数=反码+1 | `0 0111110` | `1 1000010` |

[来源：第2章 p22]

#### 例题结论

- **【码制转换练习】**
  - $[90]_原 = 01011010$，$[-78]_原 = 11001110$
  - $[90]_反 = 01011010$，$[-78]_反 = 10110001$
  - $[90]_补 = 01011010$，$[-78]_补 = 10110010$
  
  [来源：第2章 p22，Quiz]

#### 易错点与辨析

- **为什么用补码**：
  1. 符号位可以和数值位一起参加运算
  2. 0的表示唯一（`00000...00`），多出一个最小负数
  
  [来源：第2章 p22，Notes]

---

### 2.12 实型（浮点型）

#### 定义/语法

- **实型数表示**：$a \times 2^b$ 的形式（$a$ 为尾数，$b$ 为指数）
  - 尾数表示有效数值
  - 指数表示小数点位置
  - 又称**浮点表示法**
  
  [来源：第2章 p23]

- **实型占用内存**：

| 类型 | 占用空间 | 精确度 | 范围 |
|------|----------|--------|------|
| `float` | 4字节 | 7位 | $-10^{38}$ ~ $10^{38}$ |
| `double` | 8字节 | 16位 | $-10^{308}$ ~ $10^{308}$ |

[来源：第2章 p24]

#### 易错点与辨析

- ⚠️ **浮点数很多情况下只是近似表示，而不是精确值**
  [来源：第2章 p24，Notes]

---

### 2.13 字符型

#### 定义/语法

- **字符类型（`char`）**：存放一个字母或符号，占**一个字节**
  [来源：第2章 p25，数据类型-字符型]

- 字符的机内表示用**字符编码**，常用的有 **ASCII**
  [来源：第2章 p25]

- **字符赋值方式**：
  ```cpp
  char c1, c2;
  c1 = 'a';   // 字符输入（用单引号）
  c1 = 97;    // 编码输入（ASCII码值）
  ```
  [来源：第2章 p27，可打印字符的使用]

#### 规则/规范

- 字符型变量可执行的运算**与整型雷同**
  [来源：第2章 p26]

#### 例题结论

- **【字符运算】**
  - `c = 9` 与 `c = '9'` 不同：前者是整数9，后者是字符'9'（ASCII=57）
  - 若 `c1 = 'a'`，则 `c1 + 2` 为 `'c'`（即第几个字母+2）
  - 若 `c` 是小写字母，则 `c - 'a' + 1` 表示**第几个字母**
  - 若 `c` 是数字字符（'0'~'9'），则 `c - '0'` 表示**数字本身**
  - 若 `c1, c2` 是小写字母，则 `c2 - c1` 表示**字母间的距离**
  
  [来源：第2章 p27]

---

### 2.14 转义字符

#### 定义/语法

- **转义字符**：用反斜杠 `\` 加字符表示非打印或难打印的字符

| 字符形式 | 含义 |
|----------|------|
| `\n` | 换行 |
| `\t` | 水平制表 |
| `\b` | 退一格 |
| `\r` | 回车 |
| `\f` | 换页 |

[来源：第2章 p28，转义字符]

#### 规则/规范

- `'\n'` 虽然写成两个符号（反斜杠 + 字母），但它表示**一个字符常量**（换行字符），具体编码值取决于执行字符集/平台。
  [来源：第2章 p28]

---

### 2.15 布尔型

#### 定义/语法

- **布尔型（`bool`）**：表示真伪，占**一个字节**
  [来源：第2章 p29]

- **布尔值**：`true`（内部表示为1）、`false`（内部表示为0）
  [来源：第2章 p29]

#### 规则/规范

- 布尔型数据可以进行**算术、关系、逻辑运算**
  [来源：第2章 p29]

- ✅ `bool` **可以直接输入/输出**：默认情况下 `cout` 输出 `0/1`；配合 `std::boolalpha` 可输出/输入 `true/false`。有时也会用整型做“周转”来实现自定义格式或兼容旧接口，但不是必须。
  [来源：第2章 p29]

---

### 2.16 枚举类型

#### 定义/语法

- **定义枚举类型**：
  ```cpp
  enum 枚举类型名 {元素表};
  // 例如：
  enum weekdayT {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
  ```
  [来源：第2章 p31，定义新的枚举类型]

- **定义枚举变量**：
  ```cpp
  weekdayT weekday;
  ```
  [来源：第2章 p31]

#### 规则/规范

- **内部表示**：采用整数编码，默认从0开始
  ```cpp
  // 默认：0代表Sunday，1代表Monday，...，6代表Saturday
  ```
  [来源：第2章 p32，枚举类型的内部表示]

- 枚举变量使用：
  - **赋值**：`weekday = Friday;`
  - **比较**：`Monday < Friday`（比较内部整数值）
  
  [来源：第2章 p32]

- ⚠️ 枚举的输入输出要分情况：**非限定枚举（`enum`）**通常可隐式转为整数，`cout << e;` 往往会输出其底层整数值；**限定枚举（`enum class`）**不允许隐式转换，需 `static_cast` 输出/比较底层值。输入一般用“读整数再转换”或自定义映射更稳妥。
  [来源：第2章 p32]

---

### 2.17 常量

#### 定义/语法

- **常量**：在编写程序时，值已确定且不允许修改的量
  [来源：第2章 p33，整型常量]

- **整型常量表示**：
  - 十进制：`123`, `-234`
  - 八进制：以 `0` 开头，如 `0123`
  - 十六进制：以 `0x` 或 `0X` 开头，如 `0x123`, `0x3a2f`
  
  [来源：第2章 p33]

- **浮点数常量表示**：
  - 十进制：`1.23`, `3.14`, `-5.988`
  - 科学计数法：`123e2`（=12300），`2.25e-3`（=0.00225）
  
  [来源：第2章 p34，浮点数常量]

- **字符常量**：用一对**单引号**括起来，如 `'a'`, `'S'`, `'2'`
  [来源：第2章 p35，字符常量]

#### 易错点与辨析

- ⚠️ 科学计数法要求：
  - 尾数/指数**不能为空**：`e3`, `2e` 是非法的
  - 指数**必须为整数**：`2.5e2.3` 是非法的
  
  [来源：第2章 p34]

---

### 2.18 符号常量（const）

#### 定义/语法

- **C++建议用 `const` 定义符号常量**：
  ```cpp
  const <类型名> <常量名> = <值>;
  // 例如：
  const double PI = 3.1415926;
  ```
  [来源：第2章 p36，符号常量]

#### 规则/规范

- `const` 定义后，内容**不能被改写**
  [来源：第2章 p36，Notes]

- 相比宏定义，`const` 能解决**类型检查、代码执行效率低**的问题
  [来源：第2章 p36，Notes]

---

### 2.19 类型别名与sizeof

#### 定义/语法

- **类型别名**：给类型重新命名
  ```cpp
  typedef 原名 现名;
  // 例如：
  typedef int INTEGER;
  typedef double REAL;
  
  INTEGER n1 = 10;  // 等价于 int n1 = 10;
  ```
  [来源：第2章 p37，类型别名]

- **sizeof运算符**：了解某类型或表达式占用的内存量（字节）
  ```cpp
  sizeof(类型名)    // 或 sizeof(表达式)
  sizeof(float)         // float类型占用的内存量
  sizeof('a' + 15)      // 表达式结果所占内存量
  ```
  [来源：第2章 p38，了解占用的内存量]

---

### 2.20 cout输出

#### 定义/语法

- **输出流对象 `cout`**：代表标准输出设备（一般是显示器）
  [来源：第2章 p40，Cout输出]

- **流运算符**：`<<`（箭头指向数据流动方向）
  [来源：第2章 p40]

- **输出格式**：
  ```cpp
  #include <iostream>
  cout << a;                        // 输出一个变量
  cout << a << b << c;              // 输出多个变量
  cout << 12345;                    // 输出常量
  cout << a << '+' << b << '=' << a+b << endl;  // 组合输出
  ```
  [来源：第2章 p40]

---

### 2.21 cin输入

#### 定义/语法

- **输入流对象 `cin`**：代表标准输入设备（一般是键盘）
  [来源：第2章 p42，Cin输入]

- **流运算符**：`>>`
  [来源：第2章 p42]

- **输入格式**：
  ```cpp
  #include <iostream>
  cin >> 变量;
  cin >> 变量1 >> 变量2 >> ... >> 变量n;
  ```
  [来源：第2章 p42]

#### 规则/规范

- 程序执行到输入语句时会**停下来等待**用户输入
  [来源：第2章 p42]

- 用**回车**结束输入
  [来源：第2章 p42]

- 多个输入数据时，用**空白字符（空格、制表符、回车）分隔**
  [来源：第2章 p42]

---

### 2.22 cin.get

#### 定义/语法

- **从键盘接受一个字符**（不支持其他数据类型）：
  ```cpp
  char ch;
  cin.get(ch);       // 方式1
  ch = cin.get();    // 方式2
  ```
  [来源：第2章 p43，cin.get]

#### 例题结论

- **【执行结果分析】**
  ```cpp
  char a, b, c;
  a = cin.get();
  b = cin.get();
  c = cin.get();
  // 输入 "1 2 3↙"，结果：a='1', b=' ', c='2'
  
  cin >> a >> b >> c;
  // 输入 "1 2 3↙"，结果：a='1', b='2', c='3'
  ```
  **要点**：`cin.get()` 读取包括空格在内的每个字符；`cin >>` 会跳过空白字符
  [来源：第2章 p43]

---

### 2.23 格式化输入/输出

#### 定义/语法

- 使用带参数的流操纵符需包含：
  ```cpp
  #include <iomanip>
  ```
  [来源：第2章 p44]

- **设置域宽**（`setw`）：
  ```cpp
  int x, y;
  cin >> x >> y;
  cout << setw(5) << x << setw(5) << y << endl;
  // 输出 "  123  456"（各占5位）
  ```
  [来源：第2章 p44，格式化输入/输出]

- **设置精度**（`setprecision` 或 `precision`）：
  ```cpp
  double x = 123.456789;
  cout.precision(8);
  cout << x << endl;           // 输出 123.45679
  cout << setprecision(5) << x; // 输出 123.46
  ```
  [来源：第2章 p45-46]

- **设置基数**：
  ```cpp
  cout << hex << n;    // 十六进制输出
  cout << oct << n;    // 八进制输出
  cout << dec << n;    // 十进制输出
  cout << setbase(8);  // 设置为八进制
  ```
  [来源：第2章 p47-48]

#### 规则/规范

- `setw` 设置的宽度**仅适用于下一次**输入或输出，之后恢复默认
  [来源：第2章 p44]

- 精度设置会**影响之后所有**浮点数输出，直到下一次设置
  [来源：第2章 p45]

- 基数设置会**持续有效**，直到被更改
  [来源：第2章 p47]

---

### 2.24 算术表达式

#### 定义/语法

- **算术运算符**：`+`, `-`, `*`, `/`, `%`
  [来源：第2章 p53，算术表达式]

- **优先级**：
  - 高：`*`, `/`, `%`
  - 低：`+`, `-`
  - 括号内优先，同级从左到右
  
  [来源：第2章 p53]

- 运算对象可以是**整型、浮点型、字符型和布尔型**
  [来源：第2章 p53]

---

### 2.25 混合运算与类型转换

#### 规则/规范

- **C++允许不同类型进行算术运算**：编译器会按“**整型提升 + 常规算术转换（usual arithmetic conversions）**”把运算数转换为共同类型后再计算；结果类型通常是该共同类型（如 `int + double` 会把 `int` 转为 `double`，结果为 `double`）。
  [来源：第2章 p55，各种类型的数据的混合运算]

- **转换总原则**：
  1. 非标准类型转换成标准类型（`bool`, `char`, `short` → `int`）
  2. 占用空间少的转换成占用空间多的
  3. 数值范围小的转换成数值范围大的
  
  [来源：第2章 p55]

- 具体规则：
  - `int` 和 `long long` 运算时，`int` → `long long`
  - `int` 和 `double` 运算时，`int` → `double`
  
  [来源：第2章 p55]

#### 例题结论

- **【混合运算示例】**
  - `5/6*11.0` 结果为 `0.0`（5/6先算得0，再转double）
  - `11.0*5/6` 结果为 `9.166...`（11.0*5先算得55.0，再除6）
  
  [来源：第2章 p55，Notes]

---

### 2.26 赋值表达式

#### 定义/语法

- **赋值表达式格式**：
  ```cpp
  <变量> = <表达式>
  ```
  [来源：第2章 p56，变量赋值]

- **作用**：将右边表达式的值存入左边的变量
  [来源：第2章 p56]

#### 规则/规范

- `x = x + 2` 是正确的表达式（被赋值变量可出现在右侧）
  [来源：第2章 p56]

- **赋值时的自动类型转换规则**：

| 转换 | 更准确的规则（按 C++ 常见语义表述） |
|------|-----------------------------------|
| 浮点 → 整型 | **截断**小数部分（向 0 取整）；若结果超出目标整型可表示范围，行为可能未定义/实现定义（需避免）。 |
| 整型 → 浮点 | **数值尽量保持**；若目标浮点精度不足，会发生**舍入**；数值过大可能变为 `inf`。 |
| `double` → `float` | 舍入到最接近的 `float` 可表示值（精度变差；可能溢出为 `inf`）。 |
| `float` → `double` | **精确值不变**（`double` 能精确表示所有 `float` 值），只是表示范围/精度更大。 |
| `char`/`signed char`/`unsigned char` → `int` | 发生**整型提升（integral promotion）**，结果为对应字符的数值；符号扩展/零扩展取决于原类型是否有符号。 |
| `int` → `char` | 若值可表示则得到对应字符值；若不可表示，结果为实现定义/未定义风险（不应依赖“取低 8 位”这种假设）。 |

[来源：第2章 p57，赋值时的自动类型转换]

---

### 2.27 强制类型转换

#### 定义/语法

- **强制类型转换格式**：
  ```cpp
  (类型名) 表达式     // C风格
  类型名 (表达式)     // 函数风格
  
  // 例如：
  int x = 5, y = 8;
  double z;
  z = (double) x / y;   // z = 0.625
  ```
  [来源：第2章 p59，强制类型转换]

- **C++指明转换性质的方式**：
  - `static_cast<T>(expr)`：用于**有明确定义的类型转换**（数值类型转换、上行/下行转换的一部分场景等）；比 C 风格转换更可控，但仍可能丢精度/截断。
  - `reinterpret_cast<T>(expr)`：用于**低层次重解释**（多用于指针/位级别场景），可移植性差，风险高。
  - `const_cast<T>(expr)`：仅用于**添加/移除 `const`/`volatile` 限定**；若对象本来就是常量，对其“去 const 后写入”是未定义行为。
  - `dynamic_cast<T>(expr)`：用于**多态类型（含虚函数）**的安全向下转型/运行期检查；失败会返回 `nullptr`（指针）或抛异常（引用）。
  
  [来源：第2章 p60，转换类型]

#### 例题结论

- **【强制转换练习】**
  ```cpp
  double x, y;
  x = (double)5 + 6/11;       // x = 5.0（6/11=0）
  y = (double)(5 + 6/11);     // y = 5.0（5+0=5，再转double）
  ```
  [来源：第2章 p59]

#### 易错点与辨析

- ⚠️ 强制类型转换很可能导致错误，尤其涉及**自定义类和指针**时
  [来源：第2章 p60]

- 建议：定义变量时尽量回避，**报错后才考虑使用**
  [来源：第2章 p60，Notes]

---

### 2.28 复合赋值与多重赋值

#### 定义/语法

- **多重赋值**：
  ```cpp
  int a, b, c;
  a = b = c = 5;    // 给a, b, c均赋值5
  ```
  [来源：第2章 p61，更多关于赋值和运算]

- **复合赋值运算**：
  ```cpp
  balance += deposit;    // balance = balance + deposit;
  balance -= surcharge;  // balance = balance - surcharge;
  x /= 10;               // x = x / 10;
  salary *= 2;           // salary = salary * 2;
  ```
  [来源：第2章 p61]

#### 易错点与辨析

- ⚠️ **赋值是右结合运算符**：
  ```cpp
  double d;
  int i;
  d = i = 1.5;   // i等于1，d等于1.0（先算i=1.5得i=1，再d=i得d=1.0）
  ```
  [来源：第2章 p61]

---

### 2.29 自增自减运算符

#### 定义/语法

- **自增（`++`）、自减（`--`）**：让变量 +1 或 -1
  [来源：第2章 p62，自增、自减运算符]

- **前缀与后缀的区别**：

| 表达式 | 执行后 i 的值 | 表达式的值（赋给 j） |
|--------|---------------|----------------------|
| `j = i++`（i=3） | i=4 | j=3（先用后加） |
| `j = ++i`（i=3） | i=4 | j=4（先加后用） |
| `j = i--`（i=3） | i=2 | j=3（先用后减） |
| `j = --i`（i=3） | i=2 | j=2（先减后用） |

[来源：第2章 p62]

---

### 2.30 数学函数库

#### 定义/语法

- 使用数学函数需包含：
  ```cpp
  #include <cmath>
  ```
  [来源：第2章 p63，数学函数库]

- **常用函数**：

| 功能 | 函数 |
|------|------|
| 绝对值 | 推荐使用 `std::abs(x)`（对整数/浮点均有重载）；`std::fabs(x)` 也可用于浮点（更偏 C 风格接口）。 |
| $e^x$ | `double exp(double x);` |
| $x^y$ | `double pow(double x, double y);` |
| $\sqrt{x}$ | `double sqrt(double x);` |
| $\ln x$ | `double log(double x);` |
| $\log_{10} x$ | `double log10(double x);` |
| 三角函数 | `sin(x)`, `cos(x)`, `tan(x)` |
| 反三角函数 | `asin(x)`, `acos(x)`, `atan(x)` |

[来源：第2章 p64，cmath的主要内容]

---

## 总结

本章介绍了C++程序的总体结构及工作方式，具体包括：
1. 如何保存用户的数据（变量定义）
2. 读取用户提供的数值数据（`cin` 输入）
3. 在屏幕上显示文本和数据（`cout` 输出）
4. 对现有数据进行算术运算得到新的结果

[来源：第2章 p65，总结]

---

## 附：运算符优先级表

详见 [来源：第2章 p66-68]
