您的位置:首页 > 编程语言 > C语言/C++

C语言中的函数指针和左右法则

2016-08-17 23:11 267 查看
1、一个普通的函数调用例子

//自行包含头文件
void MyFun(int x); //此处的申明也可写成:void MyFun( int );
int main(int argc, char* argv[])
{
MyFun(10);    //这里是调用MyFun(10);函数
return 0;
}
void MyFun(int x) //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}


这个MyFun函数是一个无返回值的函数,它并不完成什么事情,只是一个普通的函数,在主函数中进行调用,主函数调用MyFun函数的书写格式为: MyFun(10);

我们一开始只是从功能上或者说从数学意义上理解MyFun这个函数,知道MyFun函数名代表的是一个功能(或是说一段代码)。但是直到学习了函数指针的概念后,不得不思考函数名到底是什么东西呢??(可能你觉得这没有什么意义,不要着急,继续向下看。)

函数指针变量的申明:就象某一数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也可以存储在某个函数指针变量里面,这样,我们就可以通过这个函数指针变量来调用所指向的函数了。

在C系列语言中,任何一个变量,总是要先申明,之后才能使用的,那么,函数指针变量也应该要先申明吧?那又是如何来申明呢?以上面的例子为例,我来申明一个可以指向MyFun函数的函数指针变量FunP,下面就是申明FunP变量的方法:

void (*FunP)(int) ; //也可写成void (*FunP)(int x);

通过上面的申明可知,整个函数指针变量的申明格式如同函数MyFun的申明处一样,只不过——我们把MyFun改成(*FunP)而已,这样就有了一个能指向MyFun函数的指针FunP了。(当然,这个FunP指针变量也可以指向所有其它具有相同参数及返回值的函数)

2、通过函数指针变量调用函数

有了FunP指针变量后,我们就可以对它赋值指向MyFun,然后通过FunP来调用MyFun函数了。看我如何通过FunP指针变量来调用MyFun函数的:

//自行包含头文件
void MyFun(int x); //这个申明也可写成:void MyFun( int );
void (*FunP)(int ); //也可申明成void(*FunP)(int x),但习惯上一般不这样。
int main(int argc, char* argv[])
{
MyFun(10);     //这是直接调用MyFun函数
FunP=&MyFun;   //将MyFun函数的地址赋给FunP变量
(*FunP)(20);   //这是通过函数指针变量FunP来调用MyFun函数的

return 0;
}
void MyFun(int x)  //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}


运行上面的例子,通过函数指针可以准确无误的调用MyFun函数。

通过上面的例子,我们就会想——MyFun与FunP的类型关系类似于int 与int 的关系??函数MyFun好像是一个如int的变量(或常量),而FunP则像一个如int 一样的指针变量!!

int i,*pi;
pi=&i;          //与FunP=&MyFun比较


好像可以类似,其实不然,通过函数指针调用函数还有其他的书写格式,来完成同样的事情,如下几种书写格式:

代码之一:

//自行包含头文件
void MyFun(int x);
void (*FunP)(int );   //申明一个用以指向同样参数,返回值函数的指针变量
int main(int argc, char* argv[])
{
MyFun(10);        //这里是调用MyFun(10)函数
FunP=MyFun;       //将MyFun函数的地址赋给FunP变量
FunP(20);         //这是通过函数指针变量来调用MyFun函数

return 0;
}
void MyFun(int x) //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}


运行这个例子,准确无误的得到与上面例子同样的结果,上面的例子中出现语句:FunP=MyFun; 这就有点糊涂了,这样将MyFun值同赋值给FunP,难道MyFun与FunP是同一数据类型(即如同的int 与int的关系),而不是如同int 与int*的关系了?暂时不解释,先看看下面的代码:

代码之二:

//自行包含头文件
void MyFun(int x);
void (*FunP)(int );   //申明一个用以指向同样参数,返回值函数的指针变量
int main(int argc, char* argv[])
{
MyFun(10);        //这里是调用MyFun(10)函数
FunP=&MyFun;      //将MyFun函数的地址赋给FunP变量
FunP(20);         //这是通过函数指针变量来调用MyFun函数

return 0;
}
void MyFun(int x) //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}


代码之三:

//自行包含头文件
void MyFun(int x);
void (*FunP)(int );   //申明一个用以指向同样参数,返回值函数的指针变量
int main(int argc, char* argv[])
{
MyFun(10);        //这里是调用MyFun(10)函数
FunP=MyFun;       //将MyFun函数的地址赋给FunP变量
(*FunP)(20);      //这是通过函数指针变量来调用MyFun函数

return 0;
}
void MyFun(int x) //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}


将以上两段代码分别运行,得到的结果与前面两个例子运行的结果一致。

还有下面的例子,运行也没有问题吆!!

//自行包含头文件
void MyFun(int x);    //此处的申明也可写成:void MyFun( int );
int main(int argc, char* argv[])
{
(*MyFun)(10);    //看,函数名MyFun也可以有这样的调用格式
return 0;
}
void MyFun(int x)     //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}


你也许第一次见到吧:函数名调用也可以是这样写的啊!(只不过我们平常没有这样书写罢了)

那么,这些又说明了什么呢?可以的得到以下结论:

(1)、其实,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。

(2)、但函数名调用如果都得如(*MyFun)(10),这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10)这种形式地调用(这样方便多了并与数学中的函数形式一样,不是吗?)

(3)、为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。

(4)、赋值时,即可FunP=&MyFun形式,也可FunP=MyFun。

上述代码的书写格式,随你的喜好写成什么形式都可以!!

但是有一点需要格外注意,如下:

void MyFun(int);        //不能写成void (*MyFun)(int);
void (*FunP)(int);      //不能写成void FunP(int);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: