试论【函数指针】与【指针函数】

       前面我们探讨了数组指针和指针数组的概念,两者是那么纠结和模糊。与这概念很像,对比于函数指针和指针函数,迁移概念过来,道理还是一样的:

       函数指针强调的是指针,而指针函数强调的是函数。

      一、函数指针

前面好像也谈论过了,指针可以指向变量、数组,还可以指向函数。顾名思义,函数指针就是指向函数的指针。函数名实际上是程序在内存中起始地址

指向函数的指针可以把地址传递给函数,也可以从函数返回给指向函数的指针。

实例1:(没有使用函数指针)

/*通过一个函数求两个数的和(通过函数指针调用该函数)*/
#include <stdio.h>
int Sum(int a,int b);//声明求和函数
void main()
{
	int a,b;
	printf("请您输入两个整数:");
	scanf("%d,%d",&a,&b);
    Sum(a,b);

}
int Sum(int a,int b)
{
	int sum=a+b;
	printf("%d与%d之和是:%d\n",a,b,sum);
	return sum;
}


实例2:(使用函数指针)

/*通过一个函数求两个数的和(通过函数指针调用该函数)*/
#include <stdio.h>
int Sum(int a,int b);//声明求和函数
void main()
{
	int a,b;
	int (*fun)(int,int);
	printf("请您输入两个整数:");
	scanf("%d,%d",&a,&b);
    printf("************第一种:直接函数名调用求和函数**********");
	printf("%d+%d=%d\n",a,b,Sum(a,b));
    
	fun=Sum;
	printf("************第二种:函数指针调用求和函数************");
	printf("%d+%d=%d\n",a,b,(*fun)(a,b));
}
int Sum(int x,int y)
{
	int sum=x+y;
	printf("%d与%d之和是:%d\n",x,y,sum);
	return sum;
}

以上程序中,int (*fun)(int,int);是声明一个指向函数的指针变量,并且说指向的函数返回值是整形,有两个整型参数。由于*运算符的优先级比()运算符高,所以()不可以省略。

语句fun=Sum;表示函数指针fun指向函数Sumfun和Sum都指向函数Sum的起始地址,程序在编译阶段会翻译成一行行指令并被装入到内存区域中。
注意一点就是:(*fun)(a,b);是执行调用求和函数的,也可以写成fun(a,b)的形式,因为函数本身就是一个地址。当然,函数指针还可以作为指针传递给其他函数。

 实例3:声明一个指向函数的指针数组,并通过指针调用函数的应用。

#include <stdio.h>
void f1();
void f2();
void f3();
void main()
{
	void (*f[3])()={f1,f2,f3};//定义了一个指向函数的指针数组的声明
	int flag;
	printf("请输入一个1,2,或者3.输入0退出.\n");
	scanf("%d",&flag);
	while(flag)
	{
		if(flag==1||flag==2||flag==3)
		{
			f[flag-1]();//通过函数指针调用数组中的函数
			printf("请输入一个1,2,或者3.输入0退出.\n");
			scanf("%d",&flag);
		}
		else
		{
			printf("请输入一个合法的数(1-3),0退出.\n");
			scanf("%d",&flag);
		}
	}
	printf("程序退出.\n");
}
void f1()
{
	printf("函数f1被调用!\n");
}
void f2()
{
	printf("函数f2被调用!\n");
}
void f3()
{
	printf("函数f3被调用!\n");
}


 二、指针函数

        指针函数侧重于函数,其函数的返回值是指针类型的函数。指针函数的定义形式可以为如下格式:float* fun(int a,int b);

其中fun是函数名,前面的“*”号说明返回值的类型是指针类型,因为前面的类型标识是float,所以返回的指针指向浮点型。

 来颗栗子:(本栗子源自陈锐编著的《跟我学数据结构》p41例子)

#include <stdio.h>
int *FindAddress(int (*ptr)[4],int n);//声明查找成绩行地址函数
void Display(int a[][4],int n,int *p);//声明输入成绩函数
void main()
{
	int row,n=4;
	int *p;
	int score[3][4]={{76,86,78,79},{89,82,85,90},{88,75,86,82}};
	printf("请输入学生的编号(1或2或3).输入0退出程序.\n");
	scanf("%d",&row);
	while(row)
	{
		if(row==1||row==2||row==3)
		{
			printf("第%d个学生的成绩4门课成绩是:\n",row);
			p=FindAddress(score,row-1);//调用指针函数
			Display(score,n,p);
			printf("请输入学生的编号(1或2或3).输入0退出程序.\n");
			scanf("%d",&row);
		}
		else
		{
			printf("请输入学生的编号(1或2或3).输入0退出程序.\n");
			scanf("%d",&row);
		}
	}
}
	int* FindAddress(int (*ptrScore)[4],int n)
	{
		int *ptr;
		ptr=*(ptrScore+n);
		return ptr;
	}
	void Display(int a[][4],int n,int *p)
	{
		int col;
		for(col=0;col<n;col++)
		{
			printf("%4d",*(p+col));//输出查找学生的每门课成绩
		}
		printf("\n");
	}

在程序中,main()通过调用函数FindAddress(score,row-1);把二维数组的行地址传递给*FindAddress(int (*ptr)[4],int n)的形式参数ptrScore,执行语句ptr=*(ptrScore+n),然后返回行指针ptr,调用Display(score,n,p)输出成绩,p+col是改变列地址,即找到该学生成绩的每门课的位置,逐个输出每门课的成绩。 

 

三、总结两者的区别:

          注意指针函数与函数指针表示方法的不同,千万不要混淆。

    最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。

        (1)指针函数是指带指针的函数,即本质是一个函数函数返回类型是某一类型的指针。

         定义:类型标识符    *函数名(参数表) 

         栗子:int *f(xy); float *fun();等价于:float *ptr;ptr=*fun(a);

         首先它是一个函数,只不过这个函数的返回值是一个地址值。

         函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值.而且,在主调函数中,函数返回值必须赋给同类型的指针变量

     指针函数:当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。
 格式:类型说明符 * 函数名(参数)

      (2) 函数指针是指向函数的指针变量,即本质是一个指针变量
         int (*f) (int x); /* 声明一个函数指针 */
      f=func; /* 将func函数的首地址赋给指针f */ 
       1)  指向函数的指针包含了函数的地址,可以通过它来调用函数。
         格式:类型说明符 (*函数名)(参数)
        其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。

        2)指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
       例如:void (*fptr)();
        3)把函数的地址赋值给函数指针,可以采用下面两种形式:
        fptr=&Function;
        fptr=Function;
        3)取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
               可以采用如下两种方式来通过指针调用函数:
                  x=(*fptr)();
                  x=fptr();
    第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。

主要的区别是一个是指针变量,一个是函数。在使用是必要要搞清楚才能正确使用

 

**************************************************************************************************************************************************************************************

❤永葆一颗纯洁、宽容平和、仁慈谦卑和意气风发的心!

态度决定一切     努力改变命运


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值