从“看不懂”到“能用”:一次搞清 C 语言指针数组

摘要

在学习 C 语言指针时,很多同学会卡在"指针数组""二级指针"这些概念上,感觉代码能跑,但就是不知道有什么用。

本文通过一个学生成绩管理的小功能,把"指针数组""指向指针的指针"真正用起来,结合完整代码,逐行解释指针的变化过程,让你明白:

  • 指针数组到底解决了什么问题
  • 为什么要用"指向指针的指针"
  • 这种写法在真实程序中能做什么

如果你已经学过数组和一级指针,这篇文章可以帮你把知识真正串起来。

描述(实际使用场景)

假设我们在做一个学生成绩管理程序

  • 学校里有多个学生
  • 每个学生的成绩单独存放
  • 程序需要统一管理这些成绩数据,并依次输出

如果我们直接用二维数组,当然也能做,但灵活性不够。

真实项目里,不同学生的数据往往来自不同位置 ,这时候就非常适合用指针数组来管理。

于是我们可以这样设计:

  • 用一个整型数组 a 保存某个学生的成绩
  • 用一个指针数组 num,每个元素都指向 a 中的某一个成绩
  • 再用一个指向指针的指针 p,统一遍历这些指针

这和你给出的教材示例在逻辑上是完全一致的,只是换成了一个"能说清用途"的场景。

题解答案(思路说明)

实现思路可以分成四步:

  1. 定义一个整型数组 a,保存学生的成绩
  2. 定义一个指针数组 num,让它指向 a 中的每个元素
  3. 定义一个指向指针的指针 p,指向 num 的首元素
  4. 通过移动 p,间接访问并输出每一个成绩

这个过程看起来绕,但本质是:

用指针数组统一管理数据地址,再用二级指针进行遍历。

题解代码分析

完整代码

c 复制代码
#include <stdio.h>

int main()
{
    // 学生成绩数组
    int a[5] = {1, 3, 5, 7, 9};

    // 指针数组,每个元素指向成绩数组中的一个元素
    int *num[5] = { &a[0], &a[1], &a[2], &a[3], &a[4] };

    // 指向指针的指针
    int **p;
    int i;

    // 让 p 指向指针数组 num 的首元素
    p = num;

    // 遍历并输出成绩
    for (i = 0; i < 5; i++)
    {
        printf("%d ", **p);
        p++;
    }

    printf("\n");
    return 0;
}

关键代码逐行讲解

成绩数组
c 复制代码
int a[5] = {1, 3, 5, 7, 9};

这一步很简单,相当于存了 5 个学生成绩。

指针数组的作用
c 复制代码
int *num[5] = { &a[0], &a[1], &a[2], &a[3], &a[4] };

这里是重点

  • num 是一个数组
  • 数组里的每个元素都是 int *
  • 每个指针都指向成绩数组 a 的一个元素

你可以把它理解成:

num 不是存成绩,而是存"成绩的地址"。

指向指针的指针
c 复制代码
int **p;

这表示:

  • p 指向的是一个 int *
  • 也就是说,p 指向的是 num 里的某一个元素
p 的初始化
c 复制代码
p = num;

这一步非常关键:

  • num 代表指针数组首元素的地址

  • p 开始指向 num[0]

  • 此时:

    • *p 等价于 num[0]
    • **p 等价于 a[0]
输出逻辑
c 复制代码
printf("%d ", **p);

这是整个程序最容易让人迷糊的地方:

  • p 指向 num[i]
  • *p 得到 &a[i]
  • **p 得到 a[i] 的值
指针移动
c 复制代码
p++;

每次 p++

  • 指向下一个 num 元素
  • 间接访问下一个成绩

示例测试及结果

程序运行输出

复制代码
1 3 5 7 9

对应关系说明

p 指向 *p 的值 **p 的值
num0 &a0 1
num1 &a1 3
num2 &a2 5
num3 &a3 7
num4 &a4 9

这样一对照,二级指针的逻辑就非常清楚了。

时间复杂度

  • 程序中只有一次 for 循环
  • 循环次数为 n(这里是 5)

时间复杂度为:

复制代码
O(n)

空间复杂度

  • 成绩数组 a 占用 n 个整型空间
  • 指针数组 num 占用 n 个指针空间
  • 额外只用了一个二级指针 p

空间复杂度为:

复制代码
O(n)

总结

这段代码真正想教你的不是"怎么多写几个星号",而是:

  1. 指针数组适合用来管理多个分散的数据地址

  2. 二级指针非常适合统一遍历指针数组

  3. 这种写法在真实项目中很常见,比如:

    • 命令行参数 argv
    • 多个字符串的统一管理
    • 多个数据块的集中处理

如果你现在回头再看教材里的示例,会发现它不再是"为了考试而存在",而是一个能直接迁移到真实项目里的思想

相关推荐
oort1231 分钟前
VLStream 全开源决策式 AI 视频平台 技术视角完整说明
大数据·开发语言·人工智能·经验分享·python·开源·音视频
Cloud_Shy6181 分钟前
解读《Effective Python 3rd Edition》:从练气到老魔(第二章 Item 10 - 12)
c语言·开发语言·网络·人工智能·windows·python·编辑器
Xeon_CC3 分钟前
vs2026远程开发debian12容器的C++程序笔记
开发语言·c++·笔记
水无痕simon6 分钟前
9 C语言的基础练习
c语言·开发语言·算法
少司府7 分钟前
C++进阶:二叉搜索树
开发语言·数据结构·c++·二叉树·stl·二叉搜索树·tree
Rust研习社10 分钟前
从 LaunchBadge 到 transact-rs:SQLx 社区迈出可持续治理的第一步
开发语言·后端·rust
程序大视界20 分钟前
【C++ 从基础到项目实战】C++(九):友元与设计模式初探——打破封装的艺术
开发语言·c++·cpp
東隅已逝,桑榆非晚22 分钟前
C语言预处理详解:从宏到条件编译
c语言·笔记·算法
hhb_61822 分钟前
Bash变量不加引号:空格文件名致命陷阱
开发语言·chrome·bash
宸津-代码粉碎机23 分钟前
Spring AI企业级RAG进阶|文档智能分片调优、ES深度整合、接口限流熔断监控生产实战
java·开发语言·人工智能·后端·spring·elasticsearch·oracle