c语言指针函数和函数指针的辨析

博客主页:https://blog.csdn.net/weixin_46094737?type=blog
欢迎评论⭐留言  如有错误敬请指正!
本文由小学生廉原创,首发于 CSDN🙉🙉🙉
未来很长,值得我们全力奔赴更美好的生活!💞💞💞

指针函数

 定义:

指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。
声明格式为:*类型标识符 函数名(参数)

这似乎并不难理解,再进一步描述一下。
看看下面这个函数声明:

int fun(int x,int y);

这个声明应该都很熟悉,就是一个简单的int类型的fun函数,即返回值是一个int类型的数值

int *fun(int x,int y);

这个声明和上面的区别就在于多了一个指针标识*

而这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址

这样描述应该很容易理解了,所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。

指针函数的写法

int *fun(int x,int y);
int * fun(int x,int y);
int* fun(int x,int y);

以上三种写法都是可以的,这个写法看个人习惯,其实如果*靠近返回值类型的话可能更容易理解其定义。即第一种写法就很清晰,一看便知这是个指针函数。

示例 

#include <stdio.h>
int * fun();
int main()
{
	int *p;
	int i;
	p=(*fun)();
	for(i=0;i<2;i++)
		printf("arr[%d]=%d  ",i,*(p+i));
	return 0;
	
} 
 
int *fun()//指针函数 就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针
{
 	static arr[2]={10010,911};
 	int *p=arr;
 	return arr;
}

通过以上代码可以清晰的看出指针函数使用,定义一个arr数组,将其存储在静态区,然后使用指针*p指向数组的首地址,返回数组的首地址,在主函数中去调用这个指针函数,一次打印返回的数组值。

运行结果:arr[0]=10010  arr[1]=911

函数指针 

定义:

函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。
声明格式:类型说明符 (*函数名) (参数)
如下:

int (*fun)(int x,int y);

函数指针是需要把一个函数的地址赋值给它,有两种写法:

fun = &Function;
fun = Function;

其中加不加取地址符&都可以。因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。

调用函数指针的方式也有两种:

x = (*fun)();
x = fun();

两种方式均可,其中第二种看上去和普通的函数调用没啥区别,如果可以的话,建议使用第一种,因为可以清楚的指明这是通过指针的方式来调用函数。

示例

#include <stdio.h>
/*指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针*/
//定义一个求int类型数值平方值的指针函数,返回值为平方值的地址
int *sqare(int a)
{	
	a = a *a ;
	int *p = &a ;
	return p;//返回指针,即平方值地址
}
/*函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。*/
//先定义函数
int add(int x,int y)
{
    return x+y;
}
int sub(int x,int y)
{
    return x-y;
}
//定义一个函数指针,函数两个int型参数,函数返回值类型为int
int (*fun)(int,int);

int main ()
{
	/*指针函数*/
	printf("指针函数的示例输出:\n");
	int *m = sqare(10) ;//sqare(10)的值为地址,要赋给指针变量
    printf("10的平方为%d\n",*m) ;//打印出10的平方值
	printf("12的平方为%d\n\n",*sqare(12)) ;//打印12的平方值

	/*函数指针*/
	printf("指针函数的示例输出:\n");
	//打印add函数的地址,从以下打印结果可以看出add前加不加&符号打印结果都是一样的
	printf("不加&符号时add函数地址为%d,加&符号add函数的地址为%d。\n",add,&add);
	printf("从以上打印结果可以看出add前加不加&符号打印结果都是一样的\n");
	//函数指针fun指向add函数
	fun = add;
	printf("10加上5等于%d。\n",fun(10,5));
	//函数指针指向sub函数
	fun = &sub;
	printf("10减去5等于%d。\n\n",sub(10,5));
	//调用函数指针的方式也有两种,建议第一种,因为可以清楚的指明这是通过指针的方式来调用函数。
	int p = fun (8,6);//调用方式一
	int q = (*fun)(8,6);//调用方式二
	printf("调用方式一8减去6的结果为%d,\n调用方式二8减去6的结果为%d\n",p,q);
	
	return 0;
}

 运行结果:

二者区别

通过以上的介绍,应该都能清楚的理解其二者的定义。那么简单的总结下二者的区别:

定义不同

指针函数本质是一个函数,其返回值为指针。
函数指针本质是一个指针,其指向一个函数。

写法不同
指针函数:int *fun(int x,int y);
函数指针:int (*fun)(int x,int y);
可以简单粗暴的理解为,指针函数的*是属于数据类型的,而函数指针的星号是属于函数名的。
再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。

作业1 

#include <stdio.h>
/*
编写一个程序,声明一个3*5的数组并初始化,具体数值可随意,程序打印出
数值,然后数值翻一番,接着再次打印出新值,编写-一个函数来显示数组内容,
在编写另一个函数执行翻倍功能,数组名和数组行数作为参数由程序传递给函数
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int fuzhi(int arr[3][5],int x,int y);
int doublt(int arr[3][5],int x,int y);

int main()
{
	int arr[3][5]={0};
	fuzhi(arr,3,5);
	printf("\n");
	doublt(arr,3,5);
 	return 0;
}

int fuzhi(int arr[3][5],int x,int y)
{
	int i,j;
	srand(time(0));
	for(i=0;i<x;i++)
	{
		for(j=0;j<y;j++)
			arr[i][j]=rand()%20+1;
	}
	for(i=0;i<x;i++)
	{
		for(j=0;j<y;j++)
			printf("%d\t",arr[i][j]);
		printf("\n");
	}
}

int doublt(int arr[3][5],int x,int y)
{
	int i,j;
	for(i=0;i<x;i++)
	{
		for(j=0;j<y;j++)
			arr[i][j] *= 2;
	}
	for(i=0;i<x;i++)
	{
		for(j=0;j<y;j++)
			printf("%d\t",arr[i][j]);
		printf("\n");
	}
}

 运行结果:

作业2

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int fuzhi(int arr[],int n);
//fun(int *arr,int n,int *odd,int *even);
//int *sum_oushu(int arr[],int n);
//int *sum_jishu(int arr[],int n);
int fun(int *arr,int n,int *odd,int *even); 
int main()
{
	int i;
	int sum01=0, sum02=0;
 	int arr[10]={0};
 	int *odd,*even;
 	fuzhi(arr,10);
 	for(i=0;i<10;i++)
 	{
 		printf("%d ",arr[i]);	
	}
	printf("\n");
	odd = &sum01;
	even = &sum02;
	fun(arr,10,odd,even);
	printf("偶数之和为:%d\n",*odd);
	printf("奇数之和为:%d",*even);
	
 	return 0;
}

int fuzhi(int arr[],int n)
{
	int i;
	srand(time(0));
	for(i=0;i<n;i++)
	{
		arr[i]=rand()%10+1; 
	}
}

//int *sum_oushu(int arr[],int n)
//{
//	int i,sum=0;
//	for(i=0;i<n;i++)
//	{
//		if(arr[i]%2==0)
//			sum += arr[i];
//	}
//	int *even=&sum; 
//	printf("%d",*even);
//	return even;
//}
//
//int *sum_jishu(int arr[],int n)
//{
//	int i,sum=0;
//	for(i=0;i<n;i++)
//	{
//		if(arr[i]%2!=0)
//			sum += arr[i];
//	}
//	int *odd=&sum;
//	return odd;
//}
int fun(int *arr,int n,int *odd,int *even)
{
	int i;
	int j;
	for(i=0;i<n;i++)
	{
		if(arr[i]%2==0)
			*odd += arr[i];
	}

	for(j=0;j<n;j++)
	{
		if(arr[j]%2!=0)
			*even += arr[j];
	}
}

运行结果: 

作业3 

#include <stdio.h>

int add(int x,int y)
{
    return x+y;
}
int sub(int x,int y)
{
    return x-y;
}
int cheng(int x,int y)
{
    return x*y;
}
int chu(int x,int y)
{
    return x/y;
}

int (*fun[4])(int,int)={add,sub,cheng,chu};//函数指针,将函数功能模块封装起来,由一个函数指针数组(*fun[])统一管理 

int main ()
{
	int x,y;
	char ch; 
	printf("请输入运算符:\n");
	ch=getchar();
	switch(ch)
	{
		case '+':
			printf("请输入两个整数:\n");
			scanf("%d %d",&x,&y);
			printf("%d+%d=%d",x,y,fun[0](x,y));
			break;
		case '-':
			printf("请输入两个整数:\n");
			scanf("%d %d",&x,&y);
			printf("%d-%d=%d",x,y,fun[1](x,y));
			break;
		case '*':
			printf("请输入两个整数:\n");
			scanf("%d %d",&x,&y);
			printf("%d*%d=%d",x,y,fun[2](x,y));
			break;
		case '/':
			printf("请输入两个整数:\n");
			scanf("%d %d",&x,&y);
			printf("%d/%d=%d",x,y,fun[3](x,y));
			break;
		default:
			break;
	}
//	fun = &add;
//	printf("10加上5等于%d\n",fun(10,5));
//	fun = &sub;
//	printf("10减去5等于%d\n",fun(10,5));
//	fun = &cheng;
//	printf("10乘以5等于%d\n",fun(10,5));
//	fun = &chu;
//	printf("10除5等于%d",fun(10,5));
	
	return 0;
}

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不掉头发的程序猿_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值