前言
在C语言学习过程中,指针属于重难点,很多同学容易混淆指针数组、数组指针、指针函数、函数指针几组概念,做题写代码经常踩坑。本文结合课堂笔记,梳理四类高频指针知识点,区分概念本质、语法、使用场景以及易错禁区,适合期末复习、刷题巩固,帮助理清指针相关的逻辑,避开野指针、参数类型不匹配等常见bug。
1 指针数组
本质:数组,数组中存储的元素为指针。
语法格式:
int *a[5];
char *p[5];
int *a[5] 代表定义数组,数组可以存放5个 int* 类型指针;64位环境下一个指针占8字节,整个数组总大小40字节。
1.1 初始化
// 将数组内全部指针初始化为空指针
char *p[5] = {NULL};
// 存放字符串常量,数组保存每个字符串的首地址
char *p[5] = {"hello","world","how","are","you"};
p[0] 为 char* 类型,保存字符串 "hello" 首字符 h 的地址。
1.2 指针数组 VS 二维字符数组(考试高频考点)
//二维字符数组:存储字符串本体,总字节数3*100=300字节
char str[3][100] = {"hello","world","how"};
//指针数组:仅存储各个字符串的首地址,3个指针,64位下占24字节
char *pstr[3] = {"hello","world","how"};
项目 二维字符数组 char str[N][100] 指针数组 char *pstr[N]
存储内容 保存字符串本身 保存各个字符串的首地址
数组名退化类型 数组指针 char (*)[100] 二级指针 char **
字符修改 可以修改数组内每一个字符 字符串常量空间不可修改
排序交换 需要strcpy拷贝字符串,开销大 直接交换指针,效率高
⚠注意:二者类型不同,不能互相作为函数实参传递,会报类型不匹配警告。
2 二级指针
本质:指针,用于存放另一个指针变量的地址。
int **p; //保存int*类型指针变量的地址
char **p; //保存char*类型指针变量的地址
二级指针两大使用场景
1. 函数内部修改外部的指针变量
想要在被调用函数修改主函数的指针变量,实参传递指针变量的地址,形参使用二级指针接收。
2. 接收指针数组
指针数组的数组名传参时会退化为二级指针,函数形参用 char ** 接收。
示例代码:
void func(char **p)
{
}
int main()
{
char *arr[] = {"aa","bb"};
func(arr); //数组名arr退化为 char**
return 0;
}
3 指针函数(返回指针的函数)
本质:函数,该函数的返回值是指针类型。
char* fun(void); //指针函数,返回char*指针
✅允许返回的地址
1. static修饰的静态变量的地址
2. 全局变量的地址
3. 字符串常量的地址
4. 函数参数传递进来的内存地址
5. 堆上申请、尚未释放的内存地址
❌禁止返回
局部普通变量、局部数组的地址。函数执行结束,局部栈内存被回收,返回得到野指针。
错误示例:
int* bad(void)
{
int a = 10;
return &a; //错误,返回野指针
}
4 函数指针
本质:指针,专门用来存放函数的入口地址;函数名本身就是函数入口地址。
4.1 定义语法
返回值类型 (*指针名)(形参类型);
示例:
//定义函数指针pfun,指向返回int、拥有两个int参数的函数
int (*pfun)(int,int);
4.2 完整使用示例
#include <stdio.h>
int add(int a,int b)
{
return a+b;
}
int main(void)
{
//1.定义初始化为空
int (*pfun)(int,int) = NULL;
//2.赋值,保存函数入口地址
pfun = add;
//3.调用函数,两种写法等价
int ret = pfun(10,20);
//int ret = add(10,20);
printf("%d",ret);
return 0;
}
4.3 核心应用:回调函数
将函数指针作为另一个函数的参数进行传递,这个传入的函数称为回调函数;
主要作用:降低代码耦合度。
📌易混概念速查表
写法 名称 本质 传参退化类型
char *p[5] 指针数组 数组,数组元素为指针 char **
char (*p)[100] 数组指针 指针,指向一维数组 无
char* fun() 指针函数 函数,返回指针 无
int (*p)(int,int) 函数指针 指针,保存函数入口地址 无
做题小技巧:观察括号
1. (*p) 带括号:代表是指针;
2. *p[] 无括号, [] 优先和变量结合:代表是数组。
小结
本文区分了四组极易混淆的指针相关概念:指针数组、二级指针、指针函数、函数指针。
1. 指针数组是数组,存放一堆指针,传参退化为二级指针,常用来管理多个字符串常量。
2. 二级指针用来存放指针的地址,两大用途:函数内修改外部指针、接收指针数组。
3. 指针函数是函数,重点记住:不能返回局部栈变量地址,避免野指针。
4. 函数指针是指针,存储函数入口,主要用于实现回调函数,解耦代码。
指针是C语言的灵魂,做题写代码时,先分清“它到底是数组还是函数还是指针”,很多错误就可以直接规避。