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」,专注技术干货分享,期待与你相遇。