一、二维数组传参的本质(最核心)
很多人不理解:为什么二维数组传参,行可以省略,列必须写?
答案就在二维数组的本质里。
二维数组在内存中是一维连续存放
int arr[3][5] 逻辑上是3行5列,但物理上是连续15个int。
它可以理解为:一个数组,里面的每个元素又是一个数组。二维数组名,代表首行地址
arr → 指向第一行这个数组的地址,类型是: int (*)[5]
arr+1 → 指向第二行,直接跳过一行(5个int)
- 二维数组传参,本质是传数组指针
形参里写 int arr[3][5] 只是语法糖,编译器真正识别的是:
int (*arr)[5]
所以下面两种写法完全等价:
4. 为什么列必须写?
因为指针要知道:+1 跳多少字节。
int (*arr)[5] 告诉编译器:每次加1,跳过5个int。
不写列数,编译器无法计算偏移,直接报错。
二、数组指针(指向数组的指针)
- 定义
数组指针:指向一个完整数组的指针,它指向的是整个数组,不是单个元素。
写法:
() 优先级高于 [] ,所以 p 先和 * 结合 → 是指针
指向:包含5个int的数组
- 区分指针数组 vs 数组指针
- 使用场景
主要用于二维数组传参、遍历二维数组。
示例:
三、函数指针变量(指向函数的指针)
- 本质
函数名就是函数的入口地址,函数指针就是用来存这个地址的指针。
定义格式
例子:指向一个返回int、参数为两个int的函数使用步骤:
定义函数
函数指针指向它
通过指针调用函数
四、函数指针数组(存函数指针的数组)定义
把多个同类型函数指针放进一个数组里,就是函数指针数组。
写法:
fpArr 先和 [4] 结合 → 是数组
每个元素: int (*)(int,int) 函数指针
- 用途
统一管理一批功能相似的函数,为后面转移表做准备。
五、转移表(函数指针数组经典用法)
- 什么是转移表
用函数指针数组实现分支选择,替代大量 if / switch ,代码更整洁、易扩展。
- 经典案例:计算器
- 优点
不用写冗长switch
新增函数只需往数组里加
执行效率更高,可读性强
六、一张表总结(面试必背)
二维数组传参本质:退化为数组指针,列数必须写
数组指针: int (*p)[n] → 指向数组,用于二维数组
函数指针: int (*fp)(int,int) → 指向函数
函数指针数组: int (*fpArr[])(int,int) → 存函数指针
转移表:函数指针数组实现分支,优雅替代switch