CAN控制器驱动源码包:含Windows/Linux双平台工程与完整编译配置
2026/6/12 7:08:18
在学习 C 语言指针时,很多同学会卡在“指针数组”“二级指针”这些概念上,感觉代码能跑,但就是不知道有什么用。
本文通过一个学生成绩管理的小功能,把“指针数组”“指向指针的指针”真正用起来,结合完整代码,逐行解释指针的变化过程,让你明白:
如果你已经学过数组和一级指针,这篇文章可以帮你把知识真正串起来。
假设我们在做一个学生成绩管理程序:
如果我们直接用二维数组,当然也能做,但灵活性不够。
真实项目里,不同学生的数据往往来自不同位置,这时候就非常适合用指针数组来管理。
于是我们可以这样设计:
a保存某个学生的成绩num,每个元素都指向a中的某一个成绩p,统一遍历这些指针这和你给出的教材示例在逻辑上是完全一致的,只是换成了一个“能说清用途”的场景。
实现思路可以分成四步:
a,保存学生的成绩num,让它指向a中的每个元素p,指向num的首元素p,间接访问并输出每一个成绩这个过程看起来绕,但本质是:
用指针数组统一管理数据地址,再用二级指针进行遍历。
#include<stdio.h>intmain(){// 学生成绩数组inta[5]={1,3,5,7,9};// 指针数组,每个元素指向成绩数组中的一个元素int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};// 指向指针的指针int**p;inti;// 让 p 指向指针数组 num 的首元素p=num;// 遍历并输出成绩for(i=0;i<5;i++){printf("%d ",**p);p++;}printf("\n");return0;}inta[5]={1,3,5,7,9};这一步很简单,相当于存了 5 个学生成绩。
int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};这里是重点。
num是一个数组int *a的一个元素你可以把它理解成:
num 不是存成绩,而是存“成绩的地址”。
int**p;这表示:
p指向的是一个int *p指向的是num里的某一个元素p=num;这一步非常关键:
num代表指针数组首元素的地址
p开始指向num[0]
此时:
*p等价于num[0]**p等价于a[0]printf("%d ",**p);这是整个程序最容易让人迷糊的地方:
p指向num[i]*p得到&a[i]**p得到a[i]的值p++;每次p++:
num元素1 3 5 7 9| p 指向 | *p 的值 | **p 的值 |
|---|---|---|
| num[0] | &a[0] | 1 |
| num[1] | &a[1] | 3 |
| num[2] | &a[2] | 5 |
| num[3] | &a[3] | 7 |
| num[4] | &a[4] | 9 |
这样一对照,二级指针的逻辑就非常清楚了。
for循环n(这里是 5)时间复杂度为:
O(n)a占用n个整型空间num占用n个指针空间p空间复杂度为:
O(n)这段代码真正想教你的不是“怎么多写几个星号”,而是:
指针数组适合用来管理多个分散的数据地址
二级指针非常适合统一遍历指针数组
这种写法在真实项目中很常见,比如:
argv如果你现在回头再看教材里的示例,会发现它不再是“为了考试而存在”,而是一个能直接迁移到真实项目里的思想。