【无标题】

函数指针

* 函数指针和指针函数
1. 指针函数:它本身还是一个函数,只不过函数的返回值是一个指针
2. 函数指针:它是一个指针,指针指向的是一个函数的入口
指针函数常用定义形式为ret* func(args);

其中,func是一个函数,args是形参列表,ret *作为一个整体,是 func函数的返回值,是一个指针的形式。下面举一个具体的实例来做说明:

# include <stdio.h># 
include <stdlib.h>
int * func_sum(int n){    
	static int sum = 0;    
	int *p = &sum;    
	for (int i = 0; i < n; i++){        
		sum += i;    
	}    
	return p;
}

int main(void){    
	int num = 0;    
	printf("please input one number:");    
	scanf("%d", &num);    
	int *p = func_sum(num);    
	printf("sum:%d\n", *p);    
	return 0;
}

上例就是一个指针函数的例子,其中,int * func_sum(int n)就是一个指针函数,
其功能十分简单,是根据传入的参数n,来计算从0到n的所有自然数的和,其结果通过指针的形式返回给调用方。

tips:上述代码我们的sum变量加上了修饰关键词static,这是因为函数的参数值和局部变量是存储在栈区的,在这个函数结束后我们的编译器也就会自动释放这块栈区,那个这个函数内部的局部变量和参量值都会被销毁。如果我们的p指针指向的是一个局部变量sum,那么问题也就来了。在函数结束后,变量sum的内存空间就被释放了,可能都已经被别的变量给替代了,那个我们在main函数中调用函数func_sum返回的地址还能用吗?
答案是不能用,但是如果我们把sum变量改成int sum=0,然后调试,在main函数中又可能就不会出现这个问题。为什么这个问题会不出现呢?因为编译器可能会帮你把这个变量保存一段时间,如果一段时间没用它才会再被释放,所以我们也可实验:如果在函数调用后再立即访问这段空间,这段空间的内容可能不会变,但如果我们等待一段时间再访问这块内存空间,就会有不一样的结果。

 函数指针常用定义形式
ret  (*func_p)(args)

其中,ret为返回值,*p作为一个整体,代表的是指向该函数的指针,args为形参列表。其中p被称为函数指针变量 。

*** tips: (* func_p)的这个括号()是必不可少的。**

这和我们的运算优先级和结合性有关,()的运算优先级高于*,如果我们不加(),func_p就会优先结合()成为一个函数。

我们再来用一些稍微复杂的东西来说明这个知识点。

double *(*p1)(double *,int)
double *(*pa[3])(douuble*,int)
1. 第一个是一个返回值为double *,参数为double *和int的一个函数指针
2. 第二个是一个函数指针数组,每个指针的返回值都是double *,参数为double *和int。[]运算符优先级高于*,pa先和[]结合表示这是一个数组。随后和*结合表示这是一个指针数组。二个()的优先级相同,但是()的结合性是左结合性,所以(* pa[[3])优先于后面的参数列表结合,表明这是一个函数指针

函数指针的初始化和调用 和数组类型,函数名代表这函数的入口地址,所以函数指针的初始化比较简单函数指针名=函数名;我们用一个简单的例子来说明它的初始化和调用方法

#include <stdio.h>
#include <stdlib.h>
int func(int a,int b){       
	int final;       
	final = a + b;       
	printf("the final = %d\n", final);       
	return final;
	}
	int main(){       
	int (*function_p)(int, int);       
	function_p = func;//初始化       
	(*function_p)(1, 2);//二种调用方法       
	function_p(2, 3);       
	return 0;}

*** 回调函数**

函数指针一个非常典型的利用就是回调函数什么是回调函数?回调函数就是一个通过函数指针调用的函数。他将函数指针作为一个参数,传递给另外一个函数。回调函数并非由实现方直接调用,而是在特定的事件或条件发生时由另一方直接调用的。我们可以看一个回调函数的例子。

#include<stdio.h>
#include<stdlib.h>
//函数功能:实现累加求和
int func_sum(int n)
{      
	  int sum = 0;       
	   for (int i = 0; i < n; i++){
	                   sum += i;        
	   }        return sum;}//这个函数是回调函数,其中第二个参数为一个函数指针,通过该函数指针来调用求和函数,并把结果返回给主调函数
	   int callback(int n, int (*p)(int))
	   {       
	    	return p(n);}int main(void){       
	    	 int n = 0;        
	    	 printf("please input number:");        
	    	 scanf("%d", &n);        
	    	 printf("the sum from 0 to %d is %d\n", n, callback(n, func_sum));       //此处直接调用回调函数,而不是直接调用func_sum函数        
	    	 return 0;
	    } 

上面这个简单的demo就是一个比较典型的回调函数的例子。在这个程序中,回调函数callback无需关心func_sum是怎么实现的,只需要去调用即可。这样的好处就是,如果以后对求和函数有优化,比如新写了个func_sum2函数的实现,我们只需要在调用回调函数的地方将函数指针指向func_sum2即可,而无需去修改callback函数内部
* typedef和函数指针的综合应用
typedef void (* TaskFunction_t)( void * );
在这样定义之后,我们就可以直接用TaskFunction这个别名来代指 void (* )(void *)类型的函数指针

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值