欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言函数指针

程序员文章站 2022-06-19 08:53:26
...

前几天楼主去某家公司面试实习生,面试官问了我:请讲一下函数指针。
我当时就有点懵,没回答上来,回来之后很遗憾。
今天我们就来分析一下吧。


函数指针:

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

在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);
}

实际上funfunction都指向同一个入口地址,不同就是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

相关标签: interview