C语言函数指针
前几天楼主去某家公司面试实习生,面试官问了我:请讲一下函数指针。
我当时就有点懵,没回答上来,回来之后很遗憾。
今天我们就来分析一下吧。
函数指针:
一个数据变量的内存地址可以存储在相应的指针变量中,函数的首地址 也以存储在某个函数指针变量中。这样,我就可以通过这个函数指针变量来调用所指向的函数了。
在C系列语言中,任何一个变量,总是要先声明,之后才能使用的。函数指针变量也应该要先声明。
函数指针变量的声明:
void (*fun)(int) ; //声明一个指向 具有同样参数、返回值的函数 的指针变量。
普通函数的声明:
void function(int); //声明一个函数,也可以写作 void function(int x)
整个 函数指针 变量的声明格式如同函数 void function(int)
的声明一样,只不过我们把 function
改成(*fun)
而已,这样就有了一个能指向function
函数的 指针 了。当然,这个 fun
指针变量也可以指向所有其它 具有相同参数及返回值的函数。
有了fun
指针变量后,我们就可以对它赋值指向function
,然后通过fun
来调用function
函数了。
//自行包含头文件
void function(int x);
void (*fun)(int );
int main(int argc, char* argv[])
{
fuction(10); //这是直接调用function函数。也可以写成 (*fuction)(10);
fun=&function; //将function函数的首地址赋给fun变量。也可以写成 fun=function;
(*fun)(20); //这是通过函数指针变量fun来调用function函数的。也可以写成 fun(20);
}
void fuction(int x) //这里定义一个MyFun函数
{
printf(“%d\n”,x);
}
实际上fun
和function
都指向同一个入口地址,不同就是fun
是一个指针变量,不像函数名称那样是死的,它可以指向任何函数,就看你想怎么做了。
在程序中把哪个函数的地址赋给它,它就指向哪个函数。而后用指针变量调用它,因此可以先后指向不同的函数。
结论:
1、function
函数名是一个函数指针常量,而fun
是函数数指针变量。但函数指针变量跟普通的指针一样在32位系统下大小都为4,但是函数指针常量的大小为1。
2、函数名调用如果都得如(*function)(100)
这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许function(100)
这种形式地调用,这样方便多了,便于我们调用。
3、 赋值时,即可fun=&function
形式,也可fun=function
,将函数function
的首地址赋给指针fun
。
函数指针作为某个函数的参数
在实际程序的应用中,我们可以使用函数指针作为函数的参数使用。间接调用作为参数的函数。
#include<stdio.h>
void MyFun1(int x); //声明函数,参数类型和个数还有返回值要和函数指针FunType的形式一样
void MyFun2(int x); //声明函数,参数类型和个数还有返回值要和函数指针FunType的形式一样
void MyFun3(int x); //声明函数,参数类型和个数还有返回值要和函数指针FunType的形式一样
typedef void (*FunType)(int x);
//在void (*FunType)(int )前加了一个typedef 。这样只是定义一个名为FunType函数指针类型,
//而不是一个FunType变量。也可以写成 typedef void FunType(int);
void CallMyFun(FunType fp,int);//参数fp的类型是FunType
int main(int argc, char* argv[])
{
CallMyFun(MyFun1,10);
CallMyFun(MyFun2,20);
CallMyFun(MyFun3,30);
}
void CallMyFun(FunType fp,int x)
{
fp(x);//通过fp的指针执行传递进来的函数,注意fp所指的函数是有一个参数的,也可以写成 (*fp)(x);
}
void MyFun1(int x)
{
printf("函数MyFun1中输出:%d\n",x);
}
void MyFun2(int x)
{
printf("函数MyFun2中输出:%d\n",x);
}
void MyFun3(int x)
{
printf("函数MyFun3中输出:%d\n",x);
}
执行结果:
函数MyFun1中输出:10
函数MyFun2中输出:20
函数MyFun3中输出:30
--------------------------------
Process exited after 1.353 seconds with return value 0
Press any key to continue . . .
函数指针数组:
//在定义函数指针数组的时候,已经确定了每个成员所对应的函数。
void(*Array[])(void)={Stop,Run,Jump};
Array[1]();//执行Run函数
先定义一个函数指针数组,在需要的时候为其赋值。为了还原其本来面目,我们先对这个执行特定类型的函数指针进行类型重定义,然后再用这个新数据类型来定义数组。如下:
typedef void(*Funcint)(void);//此类型的函数指针指向的是无参、无返回值的函数。
Funcint Array[32];//定义一个函数指针数组,其每个成员为INTFUN类型的函数指针
Array[10]=INT_TIMER0;//为其赋值
Array[10]();//调用函数指针数组的第11个成员指向的函数
结论
函数指针其实没有我想象中的那么难,关键要有面对难题的勇气。
1、函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。
这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。
2、有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样
参考:
https://www.cnblogs.com/huangzhenxiong/p/7772627.html
https://baike.baidu.com/item/%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88/2674905?fr=aladdin