指针(3) 函数指针、函数指针数组、函数指针数组的指针 补充:回调函数

接着指针2,继续学习指针!

三、数组参数、指针参数(此处不细讲,只看两个问题理解一下就好)

       1.当一个函数的参数部分为一级指针时,函数能接受什么参数?

       1)对应的类型的一级指针     2)对应类型的一维数组名

 如:void f(int *a,int n) ;     void f(int a[],int n);

        2.当函数的参数为二级指针时,可以接收什么参数?

        1)应用于二维数组: void f(int a[][n],int n,int m)  对于二维数组做参数一定要先指定列数!

        2)普通二级指针:void f(int **p){}   int a=0; int *p=&a; f(&p);   

       //此处只能传入普通二级指针,不能传入二维数组   原因:由于二维数组要先确定长度问题,因此不能像一维数组那样直接用

           数组名代替一级指针当参数

四、函数指针

        1.函数指针:是指向函数的指针变量。因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。

           函数指针有两个用途:调用函数和做函数的参数。

        2.函数指针的声明方法为:

          返回值类型 ( * 指针变量名) ([形参列表]);

          如:void (*pfun)(int,int); //声明了一个无返回值类型,带两个int 类型参数的函数指针。pfun是一个指针

          注:区别于指针函数: void *pfun(int,int);//这是一个函数声明语句  pfun是函数名。

          编码示例:

#include <stdio.h>
int max(int a,int b);
int min(int a,int b);
int main()
{
	int a=3,b=8;
	int (*pfun)(int,int);//定义函数指针变量
        int res;
	pfun=max;
	res=pfun(a,b);
	printf("max:%d\n",res);

	pfun=min;
	res=pfun(a,b);
	printf("min:%d\n",res);
	return 0;
}
int max(int a,int b)
{
	return a>b? a:b;
}
int min(int a,int b)
{
	return a<b? a:b;
}

总结:函数指针能代替相应类型的函数名工作。

补充:函数名就相当于每个函数的入口地址。所以当函数指针指向函数时就相当于找到了打开函数的钥匙,所以可以用函数指针进入函数。

五、函数指针数组、函数指针数组的指针

      1.函数指针数组:存放函数地址的数组。即数组元素全为函数指针的数组。

       如:int  (*parr[10])();//该数组可存放10个int类型,无参函数的地址

       用途:当要操作多个函数时可考虑用函数指针数组。

       示例:转移表(计数器的实现)

#include <stdio.h>
int add(int x,int y);//加
int sub(int x,int y);//减
int mul(int x,int y);//乘
int div(int x,int y);//除
void show();//菜单显示
void calc(int input,int x,int y,int (*p[5])(int,int));//计算器!
int main()
{
	int x=0,y=0;
	int input=1;
        //定义一个函数指针数组 p
	int (*p[5])(int,int)={0,add,sub,mul,div};//转移表
        calc(input,x,y,p);
	return 0;
}
void calc(int input,int x,int y,int (*p[5])(int,int))
{
	int result=0;
	while(input)
	{
	    show();
	    printf( "请选择:" );
            scanf( "%d", &input); 
		if(input==0) 
		{
			printf("停止计算!\n");
			break;
		}
		if(input>=1&&input<5)
		{
			printf("请输入操作数:\n");
		        scanf("%d %d",&x,&y);
			result=p[input](x,y);
			printf("result=%d\n",result);
		}	
	}
}
void show()
{
	printf( "*****************\n" );
	printf( "*0:close        *\n");
	printf( "*1:+         2:-*\n" );
	printf( "*3:*	     4:/*\n" ); 
	printf( "*****************\n" ); 
    
}
int add(int x,int y)
{
	return x+y;
}
int sub(int x,int y)
{
	return x-y;
}
int mul(int x,int y)
{
	return x*y;
}
int div(int x,int y)
{
	return x/y;
}

      2.函数指针数组的指针:是一个指针,指向函数指针数组。即数组元素全为函数指针的数组。

       如:  void (*(*ppfunArr)[5]) (int,int); //就是定义了一个指针,这个指针指向的是一个长度为5的数组,而这个数组中存储都是 无参带两个int类型参数的函数的指针(地址)。可能看起来比较绕一些!下面,我将计算器用函数指针数组的指针 来实现一下。其实改动的地方不多。

       重点理解:函数指针数组 是数组! 而函数指针数组的指针是指针变量的概念! 类似之前讲过的 数组 和数组指针!只是在这 里类型不仅是平常我们见的基本类型。此处类型可以看成是函数!

#include "stdafx.h"
int add(int x,int y);
int sub(int x,int y);
int mul(int x,int y);
int div(int x,int y);
void show();
//改1:void calc(int input,int x,int y,int (*p[5])(int,int))
void calc(int input,int x,int y,int (*(*pparr)[5])(int,int));//将参数 函数指针 改为函数指针参数的指针
int main()
{
	int x=0,y=0;
	int input=1;
	//定义一个函数指针数组
	int (*p[5])(int,int)={0,add,sub,mul,div};//转移表
	//定义一个函数指针数组指针
	int (*(*pparr)[5])(int,int)=&p;
        calc(input,x,y,pparr);
	return 0;
}
void calc(int input,int x,int y,int(*(*pparr)[5])(int,int))
{
	int result=0;
	while(input)
	{
		show();
	        printf( "请选择:" );
                scanf( "%d", &input); 
		if(input==0) 
		{
			printf("停止计算!\n");
			break;
		}
		if(input>=1&&input<5)
		{
			printf("请输入操作数:\n");
		        scanf("%d %d",&x,&y);
			//改2:result=p[input](x,y);
                        //将数组名改为指针变量  p[i](x,y)==(*pparr)[i](x,y)
			result=(*pparr)[input](x,y);
			printf("result=%d\n",result);
		}	
	}
}
void show()
{
	printf( "*****************\n" );
	printf( "*0:close        *\n");
	printf( "*1:+         2:-*\n" );
	printf( "*3:*	     4:/*\n" ); 
	printf( "*****************\n" ); 
    
}
int add(int x,int y)
{
	return x+y;
}
int sub(int x,int y)
{
	return x-y;
}
int mul(int x,int y)
{
	return x*y;
}
int div(int x,int y)
{
	return x/y;
}

 总结:在我看来,凡是指向数组的指针,加上*后都可以代替数组名来使用。

 不管是之前讲过的 数组和数组指针   还是在这里讲的 函数指针数组和函数指针数组的指针其实本质上是一样的东西,只是由后者的类型变复杂了,所以理解起来会困难一些!

学习完这一次课的内容,给我最深的感悟就是,所有复杂的东西都是从最原始的逐渐添加枝叶变成的大树。遇到大问题的时候就

将其一步步简化为小的问题去逐个理解吸收。只有理解完了小的,最后才能拼成一个完整的知识体系。就如本章内容,其实最根

本的东西还是数组,指针的问题。

补充:

回调函数:

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

编码示例: 简单选择排序,用回调函数实现

#include <stdio.h>
void sort(int *a,int n,bool (*pFun)(int,int));
void output(int *a,int n);
//升序
bool less(int x,int y);
//降序
bool greater(int x,int y);
int main(int argc, char* argv[])
{
	int a[5]={2,1,4,5,3};
	output(a,5);
	printf("升序:\n");
	sort(a,5,less);
	output(a,5);
	pirntf("降序\n");
       sort(a,5,greater);
	output(a,5);
	return 0;
}
//不用回调函数时:只能单独进行升序或是降序排列  void sort(int *a,int n);
//用函数指针做参数,实现函数调用
void sort(int *a,int n,bool (*pFun)(int,int))//1.加一个参数,传递比较方法
{
	int k;int tmp;
	for(int i=0;i<n;i++)
	{
		k=i;
		for(int j=i+1;j<n;j++)
		{
			//if(a[j]>a[k])||if(a[j]<a[k])
			if(pFun(a[j],a[k]))//2.调用函数实现比较操作
				k=j;
		}
		if(k!=i)
		{
			tmp=a[k];a[k]=a[i];a[i]=tmp;
		}
	}
	
}
void output(int *a,int n)
{
	printf("\n");
	for(int i=0;i<n;i++)
	{
		printf("%d ",a[i]);
	}
	printf("\n");
}
bool less(int x,int y)
{
	return x<y;
}
bool greater(int x,int y)
{
	return x>y;
}

用了回调函数后就可以将降序和升序的选择,作为一个函数指针 的参数传入排序函数中。

如果感兴趣,可以先自己写好普通的排序,再在自己的代码上改成与上面类似的回调函数。毕竟看十遍不如自己敲一遍!

以上内容是全由个人对现阶段所学知识进行的总结整理,如果有任何问题欢迎指出!谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值