- 指针函数:本质是函数,返回值为指针
- 函数指针:本质是指针,存放函数入口地址
(一)指针函数
1.基础定义
带有指针类型返回值的普通函数,就叫指针函数。
本质 = 函数,只是它 return 返回一个内存地址(指针)
(1)通用语法
返回值类型* 函数名(形参列表);
(2)示例
char* test(int a);
解析:
char*:函数返回 char‑类型指针
test:函数名字
(int a):函数接收一个 int 参数
int* add(int x,int y);
//返回int类型指针
2.核心规则:什么地址可以 return、什么绝对不能返回
(1)禁止返回:栈区临时地址
函数内部普通局部变量、局部数组存放在栈区; 函数运行结束之后栈空间自动释放销毁,返回该地址会造成野指针、程序崩溃。
char *bad(void)
{
char buf[32] = "hello world";
return buf;
//错误!buf是栈上局部数组,函数结束内存回收
}
(2)允许返回的 5 类地址
1)static 静态变量地址
static 变量存放于静态存储区,函数结束内存不会销毁
char *fun1(void)
{
static char str[] = "hello";
return str;
}
2)全局变量的地址
全局变量生命周期等于整个程序运行周期
3)字符串常量区地址
char *fun2(void)
{
return "hello world";
//字符串常量存放在只读常量区,生命周期常驻
}
4)函数形参传进来的地址
地址来自函数外部,不归本函数栈管理,例如 strcpy 返回 dest 指针
char *strcpy(char *dest, const char *src);
5)malloc 堆区申请的内存地址
堆内存不会随函数结束自动释放,需要手动 free 回收
#include <stdlib.h>
char *fun3(void)
{
char *p = (char*)malloc(32);
return p;
}
3. 指针函数简单实操示例
#include <stdio.h>
char* get_str(int num)
{
static char arr[][10] = {"星期一","星期二","星期三"};
return arr[num];
}
int main(void)
{
printf("%s",get_str(1));
return 0;
}
4. 易错补充
- 不要混淆
char *p()(指针函数) 和char (*p)()(函数指针) 括号优先级决定类型; - 返回字符串常量指针之后,不能修改常量区字符,只读;
- 返回堆地址记得后续 free,避免内存泄漏。
(二)函数指针
1. 基础定义
本质是指针变量,专门存放函数的入口地址; C 语言当中,单独书写的函数名本身就是函数入口地址。
2. 语法详解
通用格式:
返回值类型 (*指针名)(形参列表);
- 括号必不可少,
(*指针名)强制先识别它是指针; - 如果写成
*指针名()编译器会识别成指针函数。
示例
(1)int (*pfun)(int,int);
解析:
(1)pfun 是指针变量,64 位环境占 8 字节
(2)它只能指向:返回 int、拥有两个 int 形参的函数
(2)char *(*p)(char *);
指向:返回 char*、参数为 char* 的函数
3. 函数指针完整使用流程
① 初始化为空指针
int (*pfun)(int,int) = NULL;
② 定义普通函数
int add(int a,int b)
{
return a + b;
}
③ 给函数指针赋值
函数名就是入口地址,直接赋值即可
pfun = add;
④ 通过函数指针调用目标函数
两种写法等价
int res1 = add(3,5);
int res2 = pfun(3,5);
4. 函数指针核心用途 —— 回调函数
将函数指针当作参数传递给另一个函数,被传入的函数就叫做回调函数。
作用:
1)降低代码耦合度
2)一套代码可以动态切换不同功能函数,减少重复代码
回调简单示例:
#include <stdio.h>
int add(int a,int b)
{
return a+b;
}
int sub(int a,int b)
{
return a-b;
}
//接收函数指针作为形参
void calc(int (*func)(int,int),int x,int y)
{
printf("%d\n",func(x,y));
}
int main(void)
{
calc(add,10,3);
calc(sub,10,3);
return 0;
}
(三)整理总结
1.对比
| 对比项目 | 指针函数 | 函数指针 |
|---|---|---|
| 本质 | 是函数 | 是指针变量 |
| 优先级解析 | char *fun(),先看 fun () 是函数,返回 char* | char (*p)(),*p 先执行,p 为指针 |
| 内存占用 | 函数没有单独占用变量空间 | 指针变量,64 位占 8 字节 |
| 作用 | 返回一块内存地址 | 保存函数入口、实现回调 |
2.易混点
(1)char *p[5] → 指针数组:数组,存放 char * 指针
(2)char (*p)[5] → 数组指针:指针,指向 char [5] 数组
(3)char *p() → 指针函数:函数,返回 char*
(4)char (*p)() → 函数指针:指针,指向无参 char 返回值函数
分辨口诀:先看括号
- 带
()包住 * 变量名 → 指针- 不带括号、先碰到 [] → 数组
- 不带括号、先碰到 () → 函数
3.补充
(1)函数指针类型必须和指向的函数 返回值、参数个数、参数类型完全一致,否则报错;
(2)函数名、& 函数名都是入口地址,pfun=add 和 pfun=&add 在 C 语言里面等价;
(3)数组指针、函数指针一定要加括号改变运算符优先级;
(4)指针函数千万不要返回局部栈变量地址。

1037

被折叠的 条评论
为什么被折叠?



