函数指针与指针函数

函数指针与指针函数

函数指针
定义:

函数指针本质上是指针,它是函数的指针(定义了一个指针变量,变量中存储了函数的地址)。函数都有一个入口地址,所谓指向函数的指针,就是指向函数的入口地址。这里函数名就代表入口地址。

函数指针存在的意义:

  • 让函数多了一种调用方式

  • 函数指针可以作为形参,可以形式调用(回调函数)

语法:

 返回值类型 (*变量名)(形参列表)

举例:

 int (*p)(int a,int b);
函数指针初始化

①定义的同时赋值

 //函数指针需要依赖于函数,先有函数后有指针
 ​
 //定义一个普通的函数
 int add(int a,int b)
 {
     return a + b;
 }
 ​
 //定义一个函数指针,并初始化
 //函数指针的返回类型和依赖函数的返回类型一致
 //函数指针参数个数、类型和依赖的函数一致
 int (*p)(int a,int b) = add;//赋值一定要注意函数名不能带()

②先定义后附值

 //函数指针需要依赖于函数,先有函数后有指针
 ​
 //定义一个普通的函数
 int add(int a,int b)
 {
     return a + b;
 }
 ​
 //定义一个函数指针,并初始化
 //函数指针的返回类型和依赖函数的返回类型一致
 //函数指针参数个数、类型和依赖的函数一致
 //写法1
 int (*p)(int a,int b);//赋值一定要注意函数名不能带()
 ​
 //写法2
 int (*p)(int,int);
 ​
 //给函数指针赋值
 p = add;

注意:

1.函数指针指向的函数要和函数指针定义的返回值类型,形参列表对应,否则编译报错

2.函数指针是指针,但不能指针运算,如p++等,没有实际意义

3.函数指针作为形参,可以形成回调

4.函数指针作为形参,函数调用时的实参只能是与之对应的函数名,不能带小括号( )

5.函数指针的形参列表中的变量名可以省略

案例
  • 需求:求a,b两个数的最大值

  • 代码:

     #include <stdio.h>
     ​
     /*
     定义一个函数,实现求两个数的最大值
     @param int a,int b
     @return max最大值
     */
     int get_max(int a,int b)
     {
         return a > b ? a : b;
     }
     int main()
     {
         //测试数据
         int a = 3,b = 4,c;
         //直接调用函数
         c = get_max(a,b);
         printf("%d,%d中的最大值是%d\n",a,b,c);
         
         //定义一个函数指针
         int (*p)(int,int) = get_max;
         //间接调用函数,通过指针(方式1)
         c = p(a,b);
         printf("%d,%d中的最大值是%d\n",a,b,c);
         
         //间接调用函数,通过指针(方式2)
         c = (*p)(a,b);
         printf("%d,%d中的最大值是%d\n",a,b,c);
         return 0;
     }
回调函数(了解)
定义

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时。我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

为什么要用回调函数

因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。 简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

实现
 #include <stdio.h>
 ​
 /*
 回调函数1
 */
 int callback_1(int a)
 {
     printf("hello,this is callback_1:a = %d\n",a);
 }
 /*
 回调函数2
 */
 int callback_2(int b)
 {
     printf("hello,this is callback_2:b = %d\n",b);
 }
 /*
 实现回调函数
 */
 int handle(int x,int(*callback)(int))
 {
     printf("开始执行任务!\n");
     callback(x);
     printf("结束执行任务!\n");
 }
 int main()
 {
     //要求callback_1打印输出100,
     handle(100,callback_1);
     //要求callback_2打印输出200
     handle(200,callback_2);
     return 0;
 }
指针函数
定义:

本质上是函数,这个函数的返回值类型是指针,这个函数称之为指针函数。

语法:

 数据类型 *函数名(形参列表);//写法1
 //写法2
 数据类型 *函数名(形参列表)
 {
     函数体;
     return 指针变量;
 }

举例:

 int *get(int a)
 {
     int *b = &a;
     return b;
 }
 ​
 int mian()
 {
     int *a = get(5);
     printf("%d\n",*a);
     return 0;
 }

注意:

在函数中不要返回一个局部变量的地址,因为函数调用完毕后,局部变量会被回收,使得返回的地址就不明确,此时返回的指针就是野指针。

解决方案:

如果非要访问,可以给这个局部变量添加(定义时添加)static,可以延长它的生命周期,从而避免野指针(尽量少用,因为存在内训泄露)

举例:

 #include <stdio.h>
 ​
 int *add(int a,int b)
 {
     static int sum;//提升sum的生命周期
     sum = a + b;
     return &sum;
 }
 int main()
 {
     int *res = add(5,3);
     printf("%d\n",*res);
     
     return 0;
 }
案例
  • 需求:有若干个学生,每个学生有4门成绩,要求在用户输入学生序号(参数:int id)后,能输出该学生的全部成绩(返回值:float scores[4]),用指针函数实现

  • 代码

     #include <stdio.h>
     ​
     /*
     定义一个函数,要求输入学生序号,返回学生所有成绩
     @param all:所有学生信息
     @param id:学生序号(0开始)
     @return float scores[4]
     */
     float *scores(float (*all)[4],int id)
     {
         //定义一个指针变量,用来接受查询到的某个学生的所有成绩
         float *pt;
         
         pt = *(all + id);//行偏移
         
         return pt;//返回行地址
     }
     int main()
     {
         //准备一个二维数组,存储若干个学生的成绩
         float scores[][4] = 
         {
             {60,70,80,89},
             {44,66,45,88},
             {90,98,87,100}
         };
         int m;
         printf("请输入学生序号:\n");
         scanf("%d",&m);
         prinf("第%d个学生的成绩:\n",m);
         
         //用来接收第m个学生的成绩
         float *p;
         p = search(scores,m);
         
         //遍历成绩
         for(;p < scores[m] + 4;p++)
         {
             printf("%5.2f\t",*p);
         }
         printf("\n");
         return 0;
     }

二维数组访问方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值