指向函数的指针

Author: bakari   Date: 2012.8.8

做好总结我觉得是把知识学扎实必不可少的实践环节。这个知识点是当初自己在学习这一块做的一些笔记,现在在知识提升的情况下将它重新整理一下以作巩固之用。

我们知道一段代码在内存中是由地址的,一个函数在编译时会被分配给一个入口地址,这个地址就是该函数中第一条指令的地址,这就是函数的指针。当调用一个函数时出了通过函数名来调用之外,还可以通过指向该函数的指针变量来调用。切记,和一切指针变量一样,一个指向函数的指针其初值也不能为空。因为它在使用之前必须被赋予一个真实的地址。

看下面这段代码,使用普通的函数名的方式实现函数的调用,实现矩阵法求解

 1 #include "stdio.h"
 2 #include "math.h"
 3 
 4 //intergal(x ^ 2)
 5 double func1(double a,double b)  
 6 {
 7     double sum = 0.0;
 8     double length = 0.000001;
 9     double x = a;
10     
11     while(x < b)
12     {
13         sum += x*x*length;
14         x += length;
15     }
16     return sum;
17 }
18 
19 int main()
20 {
21     double result = 0.0;
22     result = func1(0.0,1.0);
23     printf("%g\n",result);
24 }

现在改写上面的代码,使用一个指向函数的指针变量来调用函数:

 1 #include "stdio.h"
 2 #include "math.h"
 3 
 4 //intergal(x ^ 2)
 5 double func1(double a,double b)  
 6 {
 7     double sum = 0.0;
 8     double length = 0.000001;
 9     double x = a;
10     
11     while(x < b)
12     {
13         sum += x*x*length;
14         x += length;
15     }
16     return sum;
17 }
18 
19 int main()
20 {
21     double result = 0.0;
22     double (*p)(double , double);
23     p = func1;           //把函数的入口地址赋给p
24     result = (*p)(0.0,1.0);
25     printf("%g\n",result);
26 }

关于上面的代码,有如下几点说明:

(1)、double(*p)()并非是指向某一个固定的函数,它仅仅表示定义这样一个类型的变量,可以将不同的函数地址赋给它。

(2)、(*p)两侧括号不能省,p先与*结合,表面是一个指针变量,在后面的()的内容结合,表示此指针变量指向函数而非变量,如果去掉,如:double *p()表示p()的返回类型是一个指向double型变量的指针,因为()的优先级高于*,so......

(3)p = func1; 在给p赋值是,只需要给出函数名即可,并不需要给出参数,写成这样p = func1(0.0,1.0)则是ERROR!

(4)、在使用函数指针式,只需将(*p)替代函数名即可,但需要显示添加实参,即使函数不带参数,括号也不能省。

(5)、数组名可以代表数组的起始地址(首元素的地址),所以函数名也可以代表函数的入口地址(函数中的首条指令的地址)。但对于指向函数的指针变量,它只能指向函数的入口处而无法指向函数中某条具体的指令,因此,对于p+n,p++等指针运算对于指向函数的指针没有意义。

(6)、获得一个函数的地址的方法与获得一个变量的地址的方法一样,所以,p = func1;也可以写成P = &func1;但前提必须保证func1已经声明过。如:double (*p)(double , double);

 

所以,通过以上的了解,我们知道了指向函数的指针的灵活性,一个指针变量可以调用多个不同的函数,这对于程序的优化和简化都起了很大的作用。

看下面的程序,接着上面的,矩阵法求以下几个积分:

 1 #include "stdio.h"
 2 #include "math.h"
 3 
 4 //intergal(x ^ 2)
 5 double func1(double a,double b)  
 6 {
 7     double sum = 0.0;
 8     double length = 0.000001;
 9     double x = a;
10     
11     while(x < b)
12     {
13         sum += x*x*length;
14         x += length;
15     }
16     return sum;
17 }
18 
19 
20 double func2(double a,double b)  //intergal( sin(x) )
21 {
22     double sum = 0.0;
23     double length = 0.000001;
24     double x = a;
25     
26     while(x < b)
27     {
28         sum += sin(x)*length;
29         x += length;
30     }
31     return sum;
32 }
33 
34 double func3(double a,double b)  //intergal( e ^ (x ^ -2))
35 {
36     double sum = 0.0;
37     double length = 0.000001;
38     double x = a;
39     
40     while(x < b)
41     {
42         sum += exp(sqrt(x))*length;
43         x += length;
44     }
45     return sum;
46 }
47 
48 void intergal (double a,double b,double (*fun) (double,double))
49 {
50     double result = 0.0;
51     result = (*fun)(a,b);
52     printf("%g\n",result);
53 }
54 
55 int main()
56 {
57     cout<<"计算x ^ 2在0 ~ 1上的定积分结果"<<endl;
58     intergal(0.0,1.0,func1);
59 
60     cout<<"计算sin (x)在0 ~ 1上的定积分结果"<<endl;
61     intergal(0.0,3.141593,func2);
62 
63     cout<<"计算 e ^ (x ^ -2)在0 ~ 1上的定积分结果"<<endl;
64     intergal(0.0,1.0,func3);
65     return 0;
66 }

 

好了,应该对这一块有了个大概的认识了,这对于以后的学习也能起一定的帮助。


更多干货请移步我的公众号「aCloudDeveloper」,专注技术干货分享,期待与你相遇。

posted @ 2012-08-10 15:46  bakari  阅读(436)  评论(0编辑  收藏  举报