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 }
好了,应该对这一块有了个大概的认识了,这对于以后的学习也能起一定的帮助。