计算机 · C 语言
指针
Pointers
约 12 分钟 · v8
指针 & 动态内存
cs-c/pointers · COMP1521
0 / 6
1 一句话定义
指针(pointer)就是一个存着"另一块内存的地址"的变量。
想象一张便利贴,上面写着"东西放在 12 号储物柜"。便利贴本身只是一张纸,但你顺着它能找到真正的东西。指针就是这张便利贴,解引用 *p 就是去 12 号柜子把东西取出来。
2 直觉模型 · 跟着代码一步步走
下面是一段最经典的指针代码。点 单步执行,看栈区变量、堆区分配块、指针箭头如何一步步变化。
内存可视化沙盘
栈区 Stack
堆区 Heap
步骤 0 / 9
点击"播放"或"单步"开始。这里会用大白话告诉你这一步在做什么、为什么这么做。
0
已分配字节
0
已释放字节
0
泄漏字节
0
悬空指针
3 核心要点 · 4 句话学会指针
每条要点都配最小例子。把鼠标悬停在代码上能看到逐字注解。
① 取地址:&
&x 读作"x 的地址"。栈上变量 x 住在某个房间,&x 就是那个房间的门牌号。int x = 42;
int *p = &x; // p 拿到 x 的门牌号
② 解引用:*
*p 读作"按 p 这个门牌号去拿东西"。修改 *p 等价于修改 x 本身。*p = 100; // 现在 x 也变成 100
printf("%d", x); // 输出 100
③ malloc 拿一块堆内存
栈在函数返回后自动消失;如果你想要一块"长寿"内存,必须从堆要:
malloc。int *arr = malloc(10 * sizeof(int));
arr[0] = 7; // 像数组用
④ free 归还堆内存
堆不会自动收回。谁 malloc 谁 free,否则就是"内存泄漏"。
free(arr);
arr = NULL; // 良好习惯:避免悬空
4 错误实验室 · 点一下亲眼看 bug
每个卡片是一种真实会让程序崩溃的错误。点击运行,下面控制台会模拟程序输出 / 段错误 / 内存泄漏检测。
NULL 解引用
访问空指针 SIGSEGV 段错误
悬空指针
free 之后还在用 未定义行为
内存泄漏
忘记 free 内存越用越多
双重释放
同一块内存 free 两次 堆崩溃
// 点击上方任一卡片,查看错误代码与运行效果
$ ./a.out
(等待运行...)
5 即时小测 · 6 题验收
前 5 题点选项立即判定;第 6 题是压轴写码挑战——亲手写代码,逐步可视化运行,再提交判定。
去做例题:指针与堆 · 数组翻倍
去做例题Q6.压轴挑战 · 亲手写一段最小指针程序
- 在栈上声明
int x并赋初值10。 - 声明
int *p,让它指向x。 - 通过
*p把x改成42(必须用*p,不能直接写x = 42)。 - 用
malloc申请能放 3 个 int 的堆内存,赋给指针arr,并把arr[0]设为7。 - 正确
free(arr)并把arr置NULL——结束时不能有泄漏或悬空指针。
支持的 C 语法子集(点开查看)
int x = 10; // 声明 int 变量
int *p; // 声明指针(未初始化)
int *p = &x; // 声明并指向某变量
int *p = NULL; // 空指针
int *arr = malloc(3 * sizeof(int)); // 堆分配
p = &y; x = 5; p = NULL; // 赋值
*p = 42; // 解引用写入
arr[0] = 7; // 数组下标写入
free(arr); // 释放堆内存
// 以 // 开头是注释;每条语句以 ; 结尾
// 写代码后点"运行可视化",这里会高亮当前执行行
栈区 Stack
堆区 Heap
步骤 0 / 0
写完代码后点"运行可视化",这里会逐步解释每一步在做什么。
0
已分配字节
0
已释放字节
0
泄漏字节
0
悬空指针
$ ./a.out
(等待运行...)