小白记录日常学习
一、今日任务总览
| 步骤 | 内容 | 时间 |
|------|------|------|
| ① | 阅读教材:第10章 §10.4-10.7 | 80分钟 |
| ② | 用纸笔画内存图来理解指针 | 30分钟 |
| ③ | 手打并运行3个练习 | 60分钟 |
| ④ | 反复体会练习2(swap的成功) | 30分钟 |
二、今日核心知识点
2.1 指针是什么 —— 用生活类比
想象一座公寓楼:
```
普通变量 a = 42: 指针变量 p = &a:
房间号:101号 房间号:305号
房间里放着:42 房间里放着:一张纸条写"101号"
(指向101号房间)
你去101号 → 看到42 你去305号 → 看到纸条"101号"
按纸条去找101号 → 看到42
```
```c
int a = 42; // a 是普通变量,存的是 42
int *p = &a; // p 是指针变量,存的是 a 的地址(门牌号)
a → 42 // 直接取值
*p → 42 // 间接取值:先去p拿地址,再去那个地址拿值
&a → a 的地址 // 取地址
```
2.2 & 和 * —— 两个核心运算符
| 符号 | 名字 | 作用 | 例子 |
|------|------|------|------|
| `&` | 取地址 | 问"你住哪?" | `p = &a;` → p 知道 a 住哪 |
| `*` | 解引用 | "去这个地址看看" | `*p = 100;` → 去 p 存的地址,把值改成 100 |
```c
int a = 10;
int *p = &a; // p 存了 a 的地址
*p = 20; // 通过地址修改 a → a 变成 20
printf("%d", a); // 输出 20
```
**两个用 * 的场景,不要搞混**:
```c
int *p = &a; // 这里的 * 是声明:"p 是指针类型"
*p = 20; // 这里的 * 是解引用:"去 p 存的地址那里"
```
2.3 指针实现真正的 swap ★ 今天的"顿悟时刻"
第8天的失败:
```c
void swap(int x, int y) // x 和 y 是副本
{
int temp = x; // 交换副本
x = y;
y = temp;
} // 函数结束,副本销毁,原件没动
```
今天的成功:
```c
void swap(int *x, int *y) // x 和 y 存的是地址(门牌号)
{
int temp = *x; // 去 x 指向的房间,取出值
*x = *y; // 去 y 的房间,把值搬到 x 的房间
*y = temp;
}
// 调用:swap(&a, &b); ← 传的是地址!
```
一句话总结:
> 值传递 = 把文件复印一份给你,你在复印件上改
> 指针 = 把文件柜的钥匙给你,你开柜子改原件
2.4 指针与数组
```c
int arr[5] = {10, 20, 30, 40, 50};
// 下面三种方式完全等价:
arr[2] // 下标访问 → 30
*(arr + 2) // 指针偏移 → 30
*(&arr[0] + 2) // 从首地址偏移 → 30
// 数组名 arr 就是 &arr[0],是首元素的地址
```
2.5 指针算术
```c
int *p = arr;
p + 1 → 下一个 int 的位置(实际地址 +4 字节,因为 int 占 4 字节)
p++ → p 指向下一个元素
p + n → p 指向后面第 n 个元素
```
三、阅读任务(80分钟)
《C Primer Plus 第6版》第10章:
| 章节 | 内容 | 重点 |
|------|------|------|
| §10.4 | 指针简介 | ★★★ |
| §10.5 | 指针运算符 `&` 和 `*` | ★★★ |
| §10.6 | 指针与数组 | ★★★ |
| §10.7 | 指针运算 | ★★★ |
阅读方法:放慢速度。每看到一个指针例子,先在纸上画出内存图再往下看。指针不是"看"懂的,是"画"懂的。
四、动手练习(60分钟)
练习1:指针基本操作
```bash
gcc ex1_pointer_basics.c -o ex1_pointer_basics.exe
./ex1_pointer_basics.exe
```
必做:在纸上画出变量 a 和指针 p 的内存关系图。标注地址、值、箭头指向关系。这张图要自己画,不要只看代码。
练习2:真正的 swap ★★★
```bash
gcc ex2_swap_real.c -o ex2_swap_real.exe
./ex2_swap_real.exe
```
这是今天最重要的练习。运行完后:
1. 找出第8天 `day08/ex3_swap_fail.c`,再跑一遍
2. 对比两个程序的输出
3. 在纸上画出两个 swap 版本的内存图,感受"传值"和"传地址"的本质区别
如果只做一个练习,就做这个。搞懂了今天的 swap,指针就入门了。
练习3:指针数组遍历
```bash
gcc ex3_pointer_array.c -o ex3_pointer_array.exe
./ex3_pointer_array.exe
```
比较三种遍历方式,注意观察 `p+1` 的地址比 `p` 多了多少(应该刚好是一个 int 的字节数)。
五、自由实验(30分钟)
实验1:用指针实现 strlen
不调用 `string.h`,用指针实现计算字符串长度:
```c
int my_strlen(const char *str)
{
const char *p = str;
while (*p != '\0')
p++;
return p - str; // 指针相减 = 元素个数
}
```
实验2:用指针实现选择排序
把第9天的选择排序改成指针版本(用指针而非下标遍历)。
六、今日自检
- [ ] 能说清楚 `int *p = &a;` 中 `int*`、`p`、`&a` 分别是什么
- [ ] 能说清楚 `*p` 是什么(解引用,顺着地址访问值)
- [ ] 能解释第8天的 swap 为什么失败,今天的 swap 为什么成功
- [ ] 知道 `arr[i]` 和 `*(arr+i)` 是等价的
- [ ] 知道 `p+1` 跳过几个地址取决于指针的类型
- [ ] 三个练习全部运行成功
七、明天预告
第11天:字符串 — 本质上就是字符指针,学完指针再看字符串会豁然开朗。