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

拒绝晕车!从基础到进阶,一文彻底理清C语言指针与数组组合

在C语言的学习之路上,我在遇到int *p[5]int (*p)[5]甚至int (*p[5])(int, int)时,大脑会瞬间宕机。别慌,万丈高楼平地起,今天我们抛弃死记硬背,从最基础的变量开始,用一个核心法则彻底把它们拿捏!

🧱 第一阶段:前置基础(盒子与纸条)

为了方便理解,我们建立一个简单的思维模型:变量是一个装东西的“盒子”,而指针是一张写着地址的“纸条”

1. 普通变量 (int a;)

  • 概念:一个普通的整型变量。

  • 大白话:一个普通的盒子,里面直接装着一个整数(比如 100)。你想用数据,直接打开盒子拿就行。

2. 一级指针 (int *a;)

  • 概念:一个指向整型数据的指针。

  • 大白话:一张小纸条,上面写着刚才那个“装整数的盒子”的地址。你要找数据,得先看纸条上的地址,顺着地址跑过去才能找到盒子(这就叫解引用*a)。

3. 二级指针 (int **a;)

  • 概念:一个指向“整型指针”的指针。

  • 大白话:这还是一张纸条,但它上面写的不是盒子的地址,而是另一张纸条的地址!顺着这张纸条找过去,你会找到第二张纸条,再顺着第二张纸条找过去,才能找到最终装整数的盒子(解引用**a)。常用于在函数内部修改一级指针的指向。


💡 第二阶段:破局核心法则

当指针遇到数组和函数,判断一个复杂声明到底是什么,只需要记住一句话:看变量名先和谁结合

  • [](数组)和()(函数)的优先级高于*(指针)。

  • 如果有括号()改变了优先级,就先看括号里的。


⚔️ 第三阶段:组合怪兽大解密

1. 指针数组 (Array of Pointers)

概念:它首先是一个数组,数组里的每一个元素都是一个指针

语法int *p[5];

  • 拆解p先和[5]结合,说明p是一个包含5个元素的数组。剩下的是int *,说明数组里的每个元素都是整型指针。

  • 大白话:一个大盒子里,整整齐齐地摆放着5张小纸条,每张纸条上都写着一个整数的内存地址。

常见应用:存储多个字符串(字符串数组)。

C

#include <stdio.h> int main() { // 这是一个指针数组,存了3个字符串的起始地址 char *names[3] = {"Alice", "Bob", "Charlie"}; for(int i = 0; i < 3; i++) { printf("%s\n", names[i]); } return 0; }

2. 数组指针 (Pointer to an Array)

概念:它首先是一个指针,这个指针指向一个完整的数组

语法int (*p)[5];

  • 拆解:圆括号改变了优先级!p先和*结合,说明p是一个指针。剩下的是int [5],说明这个指针指向一个包含5个整型元素的数组。

  • 大白话:这就只有一张孤零零的小纸条,但这张纸条上写的地址,指向的是一个“连着装了5个整数的超大盒子”。

常见应用:二维数组的传参。二维数组的数组名,本质上就是一个指向其第一行的“数组指针”。

C

#include <stdio.h> // 接收二维数组时,形参本质上就是一个数组指针 void printArray(int (*arr)[3], int rows) { for(int i = 0; i < rows; i++) { for(int j = 0; j < 3; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } int main() { int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}}; printArray(matrix, 2); // 传入二维数组 return 0; }

3. 终极 Boss:函数指针与函数指针数组

为了打败这个 Boss,我们先认识一下它的前置形态:函数指针

  • 函数指针:指向函数的指针。语法:int (*func)(int, int);func先和*结合,是一个指针,指向返回值为int,参数为两个int的函数)。

现在升级为函数指针数组

概念:它是一个数组,数组里的每一个元素都是一个函数指针

语法int (*p[4])(int, int);

  • 拆解p先和[4]结合,说明是个数组。剩下的int (*)(int, int)是元素类型,也就是函数指针。

  • 大白话:一个盒子里装了4张纸条,每张纸条上写着一段可以执行的机器代码(函数)的地址。

常见应用:转移表(状态机、菜单系统、计算器),可以完美替代冗长的switch-case

C

#include <stdio.h> int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int main() { // 定义一个函数指针数组,并初始化,里面存了函数的地址 int (*ops[2])(int, int) = {add, sub}; int choice = 1; // 假设用户选择了减法 (索引为1) // 直接通过数组索引调用函数,告别一堆 if-else! int result = ops[choice](10, 5); printf("Result: %d\n", result); // 输出 5 return 0; }

📝 终极总结速查表

声明形式名称核心本质大白话怎么记(看变量名先和谁结合)
int a整型变量数据盒子,直接装整数
int *a一级指针指针纸条,写着装整数的盒子的地址
int **a二级指针指针纸条,写着另一张纸条的地址
int *p[5]指针数组数组先遇[]➡️ 是数组,盒子里装了5张纸条
int (*p)[5]数组指针指针括号强求先遇*➡️ 是指针,一张纸条指向一个大数组
int (*p)(int)函数指针指针括号强求先遇*➡️ 是指针,一张纸条指向一段函数代码
int (*p[5])(int)函数指针数组数组先遇[]➡️ 是数组,盒子里装了5张指向函数的纸条

希望这篇文章能帮你彻底斩断C语言指针声明的乱麻!如果觉得有帮助,欢迎点赞、收藏并在评论区交流!

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

相关文章:

  • 表格全选功能JavaScript实现深度解析
  • IBM发布2025年度报告:首席执行官Arvind Krishna致投资人的一封信
  • 排序(二)【数据结构】
  • 8个超硬核的大模型项目
  • WPS单元格格式
  • QGraphicView + QGraphicItem
  • 字节跳动 Seedance 2.0 全球发布受阻,AI 视频版权困境待解
  • C++比较三位数大小
  • 游戏数据助力配送机器人升级
  • LBM vs FVM:谁才是 CFD 的未来?
  • MSCOMCTL.OCX文件出错 免费下载修复方法分享
  • 快讯|智谱GLM-5-Turbo实测:面向OpenClaw深度优化,响应提速60%,token消耗减少17.8%
  • 渗透测试实战指南:从零基础到专业测试工程师的完整路径
  • Meta 收购爆火 AI 社交网络 Moltbook
  • 05樊珍
  • python运算符
  • 文件名批量重命名怎么按数字排序?6个简单技巧轻松搞定!
  • 用自己的声音实现PPT转视频加AI配音,小米坡PPT转视频工具v2.25操作教程
  • ASO优化服务商排名
  • 手把手教你免费获取豆包 AI API Key 并接入前端项目
  • 64 匠心古法雕塑源头工厂哪家实力强?
  • 天津守嘉陪诊 17310982305 - 品牌排行榜单
  • C语言从入门到进阶——第14讲:深入理解指针(4)
  • 2026工业园区数字孪生深度解析:视频孪生与大模型如何赋能智慧决策
  • 发芽Day2
  • 绝缘阻抗检测计算
  • 一秒推GEO中的DeepSeek收录技巧关键要素是什么?
  • 成都2026增值税法规变化要点:企业合规应对策略深度解析
  • SW - 干涉检查异常 - 要忽略隐藏的实体和零件才行
  • 别让几百万展位费,只换回一叠落灰的名片|这场展会,我们终于打赢了“时间战”