2026-08-11 周二 · 递归、构建过程与阶段 2
2026-08-11
技术
C 语言
学习内容:递归函数 + 程序构建过程
递归函数
两个关键点缺一不可: 递推关系(大→小) + 结束条件(Base Case)。
底层原理:每次调用在栈区分配栈帧(Stack Frame),存放返回地址、形参、局部变量。递���过深 → 栈空间耗尽 → Stack Overflow。
| 例子 | 递推关系 | 复杂度 |
|---|---|---|
| 阶乘 | n! = n × (n-1)! |
O(n) |
| 斐波那契 | F(n) = F(n-1) + F(n-2) |
O(2^n),大量重复计算 |
| 汉诺塔 | n-1→辅助,最大→目标,n-1→目标 | O(2^n) |
简单用循环,分治/回溯用递归。不要为了递归而递归。汉诺塔是非递归极其困难、递归极其优雅的典型案例。
C 程序构建四工序
从 .c 到可执行文件,四道工序:
hello.c → ①预处理 → hello.i → ②编译 → hello.s → ③汇编 → hello.o → ④链接 → hello
| 阶段 | 负责者 | 输入 → 输出 | 做什么 | GCC 命令 |
|---|---|---|---|---|
| ① 预处理 | 预处理器 | .c → .i |
删注释、处理 # 命令(#include copy 头文件、#define 宏替换、条件编译) |
gcc -E |
| ② 编译 | 编译器 | .i → .s |
C → 汇编代码,语法错误在此报 | gcc -S |
| ③ 汇编 | 汇编器 | .s → .o |
汇编 → 机器码,生成目标文件 | gcc -c |
| ④ 链接 | 链接器 | .o + 库 → 可执行 |
合并目标文件,解析符号引用(如 printf 地址),分静态链接和动态链接 |
gcc |
几个要点:
#include <file>vs"file"— 尖括号搜系统目录,双引号先搜当前目录- 头文件保护 — 每个
.h标配#ifndef/#define/#endif,防止重复包含 - 头文件放声明性语句 — 函数声明、
extern全局变量、#define宏、类型声明 gcc hello.c -o hello— 一步到位,四合一
Rust
学习内容:Rust Day12 笔记——阶段 2:枚举、Result、Option、自定义错误、文件 I/O
今天在 demo3.rs 里写了阶段 2 的练习:
| # | 练习 | 涉及点 |
|---|---|---|
| 1 | Shape 枚举 + area() |
match + 海伦公式 |
| 2 | Operation 枚举 + execute() |
match + Result + 除零检查 |
| 3 | parse_int / parse_float |
字符串解析,map_err |
| 4 | calculate("a/b") |
? 链式调用 |
| 5 | find_in_vec |
iter().position() |
| 6 | double_if_even |
Option::filter().map() 组合 |
| 7 | get_or_zero |
unwrap_or() |
| 8 | read_file |
match + ErrorKind::NotFound |
| 9 | copy_file |
fs::read + fs::write |
| 10 | MyError 自定义错误 |
impl Display + impl Error |
| 11 | read_config |
文件读取 + io 错误 → 自定义错误 |
| 12 | sum_numbers |
for + ?,任何一步失败就短路 |
| 13 | while let |
遍历 Vec<Option<i32>> |
几个新收获:
ErrorKind::NotFound的模式匹配写法:Err(e) if e.kind() == ErrorKind::NotFound- 自定义错误类型需要同时
impl Display和impl Error Option::filter()可以直接筛Some里的值,不符合变Nonewhile let Some(x) = iter.next()处理嵌套 Option 比for+ 判空简洁
明日计划
- C 语言:跟课堂节奏,递归章节作业
- Rust:阶段 2 收尾,进入阶段 3