c语言指针学习(5)指针函数---函数指针---回调函数

**

一、指针函数

**

在这里插入图片描述
1、指针函数定义的语法格式:

返回数值类型  *函数名(形参表)
{
		函数体语句
}

在这里插入图片描述
原来b只能在return_test内部使用,现在一旦返回了b的地址给别的函数,那么别的函数也可以访问b了,无形扩大了b的使用范围
在这里插入图片描述
打开注释return &g_a或者return &g_b打印结果是一样的
在这里插入图片描述
2、完善:
在这里插入图片描述
在这里插入图片描述

3、函数,指针,数组

void A(int a[],int length)
等价于
Void A(int *a,int length)

利用两种函数方式打印数组的元素内容,其是一样的
在这里插入图片描述
结果如下:
在这里插入图片描述
使其元素内容+1操作
在这里插入图片描述
在这里插入图片描述
可复制代码如下:

#include<stdio.h>
 static void print1(int a[],int length)//方式 1
 {   
     for(int i=0;i<length;i++)
         printf("a[%d]=%d\n",i,a[i]);
 }
 static void print2(int *p,int length)//方式2
 {   
     for(int i=0;i<length;i++)
         printf("p[%d]=%d\n",i,p[i]);
  
 }
 static void add(int *p,int length)//实现数组元素加1
 {
     for(int i=0;i<length;i++){
         p[i]+=1;
         printf("add_p[%d]=%d\n",i,p[i]);}
 }
 int main()
 {
     int a[]={1,2,3,4,5};
     int length=sizeof(a)/sizeof(a[0]);
 
     print1(a,length);
     print2(a,length);
     add(a,length);
 }

**

二、函数指针

**

1、上面的指针函数:
就是一个函数,只是函数的返回值是一个地址而已

	例如 int *add(int a ,int b)

2、明确函数名就是整个函数的首地址

例如:int add(int a,int b)
{
		Printf(“……….”);
		Printf(“……….”);
		Printf(“……….”);
}

结论:add就是函数的首地址,等于add函数中第一条语句printf这条语句的首地址,看到add就是看到了一个地址(32位,4字节)
在这里插入图片描述

4、函数指针数据类型声明的语法格式不会分配内存大型程序中写头文件中

返回值数据类型  (*函数指针名)(形参表)
例如:int (*pfunc)(int ,int);//pfunc就是一种数据类型,函数指针数据类型
或者
Typedef int (*pfunc)(int ,int);//给函数指着数据类型取别名为pfunc

5、函数指针变量定义的语法格式:函数指针名 函数指针变量

例如:
Pfunc_t  pfunc;//定义一个函数指针变量,
               //将来保存函数的首地址(pfunc_t是别名)

6、函数指针变量的初始化

pfunc_t pfunc  = add; //定义一个函数指针变量并且保存add函数
						的首地址,也就是pfunc指向add函数
或者:
pfunc_t pfunc;
pfunc = add;

7、通过函数指针变量来间接调用指向的函数的语法:
函数指针变量名(实参表)

pfunc(100, 200); //本质就是调用add函数,类似add(100, 200)

指针函数就是一个指针,特殊的地方在于保存的东西比较特殊,是保存的一个地址,以后很多函数只要定义一个指针 函数,然后挨个调用就好了

**

举例如下:

**

(1)定义加减函数
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(2)清0和置1函数

在这里插入图片描述
可复制代码如下:

/*函数指针演示*/
 #include<stdio.h>
 //声明一个函数指针类型并且取别名
 typedef void (*pfunc_t)(int *,int);
 void clear_bit(int *data,int n){//清零函数
    *data&=~(1<<n);
 }
 void set_bit(int *data,int n){//置1函数
     *data|=(1<<n);
 }
 int main(){
     int data=0x55;
     //定义函数指针变量,并且初始化为NULL
     pfunc_t pfunc=NULL;
     pfunc=clear_bit;
     pfunc(&data,2);//0101 0101--0101 0001(0x51)
     printf("data=%#x\n",data);
     pfunc=set_bit;
     pfunc(&data,3);//0101 0001--0101 1001(0x59)
     printf("data=%#x\n",data);
 }

三、函数指针经典用法

需求:目前有一堆函数,要求程序启动时,把这一堆函数挨个调用一遍

笨办法

vim pfunction3.c
#include <stdio.h>
一堆函数的定义
void add(int a, int b)
{
	return a + b;
}
...
int main(void)
{
	//挨个调用
	add(1,2);
	sub(1,2);
	mul(2,2);
	div(3,2);
	...
	return 0;
}   

优秀代码:

在这里插入图片描述
在这里插入图片描述

可复制代码如下:

#include<stdio.h>
  //声明函数指针数据类型并且取别名
  typedef int (*pfunc_t)(int,int);
  //定义一堆函数
  int add(int a,int b){return a+b;}
  int sub(int a,int b){return a-b;}
  int mul(int a,int b){return a*b;}
  int div(int a,int b){return a/b;}
  int main()
  {
      //1、定义一个函数指针数组,每个元素是一个函数的地址
      pfunc_t pfun_array[]={add,sub,mul,div,NULL};
      //2、挨个调用 
      for(pfunc_t *pfunc=pfun_array;*pfunc;pfunc++)
      {   //*pfunc是取出内容
          int ret=(*pfunc)(200,100);//取出每个函数调用
          printf("ret=%d\n",ret);
      }
      return 0;
   }

**

四、回调函数

**

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

回调函数可复制代码如下

/*回调函数演示*/
 #include<stdio.h>
 //声明一个函数指针类型(以后数据类型的别名就是pfuc_t)
 typedef int (*pfunc_t)(int ,int);
 int add(int a  ,int b){//定义加法函数:回调函数
     return a+b;
 }
 int sub(int a,int b){//定义减法函数:回调函数
     return a-b;
 }
 int cal(int a,int b,pfunc_t pfunc){
     int ret=pfunc(a,b);//调用pfunc指向的函数并且给指定的
 函数传递a,b
     return ret;
 }
 int main()
 {
     int ret=0;
 ret=cal(100,200,add);//让pfunc指向add函数,add称为回>    调函数
     printf("ret=%d\n",ret);
     ret=cal(100,200,sub);//让pfunc指向sub函数,sub称为回>    调函数
     printf("ret=%d\n",ret);
 }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永栀哇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值