当前位置: 首页 > news >正文

C 语言从 0 入门(二十)|指针进阶:指针数组、数组指针与函数指针

大家好,我是网域小星球。

前面我们学过了指针基础、指针与数组的关系。但在进阶语法、笔试面试和实际项目里,经常会遇到三个长得很像、含义却完全不同的概念,很多人学到这里直接混淆:指针数组、数组指针、函数指针

它们长得像、用法不同、坑点密集。本篇用最清晰的对比 + 案例,一次性讲透,全程 VS2022 可直接运行。

目录

一、本章学习目标

二、先破局:一句话分清两个易混概念

三、数组指针(指向数组的指针)

1. 定义

2. 用途:指向二维数组

四、指针数组(存放指针的数组)

1. 定义

2. 最常用场景:多字符串管理

五、数组指针 vs 指针数组 对比表

六、函数指针(指向函数的指针)

1. 什么是函数指针?

2. 定义格式

3. 最简单使用示例

4. 实战用途:菜单跳转 / 回调函数

七、高频易错点

八、本章核心总结

下期预告


一、本章学习目标

  1. 分清数组指针指针数组,不再混淆
  2. 掌握二维数组与数组指针的关系
  3. 理解函数指针是什么、怎么定义、怎么用
  4. 学会用函数指针实现回调、简易菜单跳转
  5. 搞定 C 语言指针进阶高频考点

二、先破局:一句话分清两个易混概念

  • 数组指针:本质是指针,指向一个数组
  • 指针数组:本质是数组,里面每个元素都是指针

口诀:后面两个字是什么,它就是什么。


三、数组指针(指向数组的指针)

1. 定义

类型 (*指针名)[数组长度];

例如:指向 5 个 int 的数组

int (*p)[5];
  • ()优先级很高
  • 先说明p是指针
  • 再说明它指向一个长度为 5 的 int 数组

2. 用途:指向二维数组

二维数组名,本质就是数组指针

int arr[2][3] = { {1,2,3}, {4,5,6} }; int (*p)[3] = arr;

访问:

// 第0行第1列 printf("%d", (*p)[1] );

完整示例

#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int arr[2][3] = { {1,2,3}, {4,5,6} }; int (*p)[3] = arr; printf("%d\n", (*p)[0]); // 1 printf("%d\n", (*(p+1))[0]); // 4 return 0; }

四、指针数组(存放指针的数组)

1. 定义

类型 *数组名[长度];

例如:长度为 3 的指针数组

int *arr[3];
  • []优先级比*
  • 先说明arr是数组
  • 每个元素是int*类型指针

2. 最常用场景:多字符串管理

char *strArr[] = { "Chinese", "Math", "English", "Programming" };

完整示例

#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { char *courses[] = { "语文", "数学", "英语", "C语言" }; for (int i = 0; i < 4; i++) { printf("%s\n", courses[i]); } return 0; }

五、数组指针 vs 指针数组 对比表

写法名字本质记忆
int (*p)[5]数组指针指针,指向数组括号包住,是指针
int *p[5]指针数组数组,存指针无括号,是数组

一句话区分:有括号是指针,没括号是数组。


六、函数指针(指向函数的指针)

1. 什么是函数指针?

函数在内存中也有地址。函数指针就是存放函数地址的指针。

2. 定义格式

返回值类型 (*指针名)(参数列表);

示例:指向参数为 (int,int)、返回 int 的函数

int (*fp)(int, int);

3. 最简单使用示例

#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int add(int a, int b) { return a + b; } int main() { // 定义函数指针 int (*fp)(int, int) = add; // 两种调用方式等价 printf("%d\n", add(2, 3)); printf("%d\n", fp(2, 3)); return 0; }

4. 实战用途:菜单跳转 / 回调函数

void show() { printf("显示信息\n"); } void add() { printf("添加数据\n"); } void exitSys() { printf("退出系统\n"); } int main() { // 函数指针数组 void (*funcArr[])(void) = { exitSys, show, add }; int choice; scanf("%d", &choice); funcArr; // 直接调用对应函数 }

这是做菜单框架、状态机、插件化的基础。


七、高频易错点

  1. int (*p)[5]写成int *p[5],含义完全相反
  2. 函数指针少写括号int *fp(int,int)变成函数声明
  3. 数组指针越界,特别是二维数组使用时
  4. 函数指针类型不匹配(返回值 / 参数对不上)
  5. 函数指针赋值时加了&或漏写&(其实都可以,但要规范)

八、本章核心总结

  1. 数组指针int (*p)[n]→ 指针,指向数组
  2. 指针数组int *p[n]→ 数组,存指针
  3. 口诀:括号是指针,无括号是数组
  4. 函数指针int (*fp)(int,int)指向函数地址
  5. 函数指针可做回调、菜单跳转、简化分支逻辑
  6. 这一章是 C 语言进阶分水岭,搞懂才算真正入门指针

下期预告

下一篇学习 typedef,给复杂类型起别名,简化数组指针、函数指针等复杂写法,让代码更简洁易读。

http://www.jsqmd.com/news/636677/

相关文章:

  • 告别笨重调幅变压器:聊聊PDM技术如何让现代中波发射机更高效、更可靠
  • 基于深度学习的YOLOv8电脑主机零部件检测项目 电脑零部件测识别 CPU风扇、螺丝、端口等多个零部件的缺陷检测
  • 期货交易实战指南:多空趋势变色线与黄金分割自动画线指标源码解析
  • 【避坑指南】移动硬盘安装Ubuntu:从RST到引导修复的完整排雷手册
  • 深入解析:计算机视觉需要哪些数学基础?如何高效学习线性代数和概率论?
  • 终极Windows 11瘦身指南:使用Win11Debloat免费工具让电脑提速50%
  • 从单体Agent到联邦智能体网络:SITS2026定义的2026架构演进路线图(含3阶段迁移checklist与兼容性断点预警)
  • 终极指南:3步掌握AlienFX Tools,轻松替代臃肿的AWCC控制软件
  • Foldseek蛋白质结构比对:高性能算法优化与大规模数据库分析技术
  • Python——常见异常
  • 告别蓝屏!用xrdp-installer-1.2脚本一键搞定Ubuntu 18.04远程桌面(附脚本下载)
  • 实测DDColor修复能力:ComfyUI工作流,让黑白记忆重获新生
  • 闲置树莓派别吃灰!用RustDesk打造跨平台远程控制中心(支持macOS合盖模式)
  • OpenBlock vs S4A:两大Arduino可视化工具对比测评(附详细配置步骤)
  • PyFluent自动化CFD仿真:如何让流体分析效率提升10倍
  • 完全掌控你的鼠标:Mac Mouse Fix终极配置指南
  • 2025年Ubuntu系统维护清单:从日志清理到Btrfs快照,让你的桌面版稳如老狗
  • 视频修复神器untrunc:三步拯救你的损坏MP4文件
  • 零样本检索落地实践:用GCN提升草图搜图准确率(AAAI2020最新方法)
  • WRF-Hydro在Ubuntu 22.04 LTS上的系统化部署与编译实战
  • RK1106 Recovery 开发与固件升级指南(超详细)
  • 遥感数字图像处理教程【2.1】
  • AD大电流开窗进阶:将动态铺铜精准转换为阻焊层静态Region的实战指南
  • 深入探索Dream DSP芯片开发环境搭建
  • GLM-OCR助力数据库课程设计:实验报告与文档自动解析入库
  • C# 面试高频题:装箱和拆箱是如何影响性能的?拇
  • 从Java转行大模型应用,大模型微调,模型微调的概念和选择合适的基座模型
  • GitHub Copilot vs Claude Code:深度对比
  • 面了个新人连Agent如何进行冷启动都不知道
  • 免费实时空气质量API接口:一站式获取AQI+PM2.5+NO2+CO+O3+SO2+PM10数据