设为首页 加入收藏

TOP

C语言函数指针入门基础
2019-01-25 14:08:54 】 浏览:82
Tags:语言 函数 指针 入门 基础

函数指针是什么?如何使用函数指针?函数指针到底有什么大用?本文将一一介绍。


 


如果有int *类型变量,它存储的是int类型变量的地址;那么对于函数指针来说,它存储的就是函数的地址。函数也是有地址的,函数实际上由载入内存的一些指令组成,而指向函数的指针存储了函数指令的起始地址。如此看来,函数指针并没有什么特别的。我们可以查看程序中函数的地址:


编译:


查看test函数相对地址(并非实际运行时的地址):


声明普通类型指针时,需要指明指针所指向的数据类型,而声明函数指针时,也就要指明指针所指向的函数类型,即需要指明函数的返回类型和形参类型。例如对于下面的函数原型:


它是一个返回值为int类型,参数是两个int类型的函数,那么如何声明该类型函数的指针呢?很简单,将函数名替换成(*pf)形式即可,即我们把sum替换成(*fp)即可,fp为函数指针名,结果如下:


这样就声明了和sum函数类型相同的函数指针fp。这里说明两点,第一,*和fp为一体,说明了fp为指针类型,第二,*fp需要用括号括起来,否则就会变成下面的情况:


这种情况下,意思就大相径庭了,它声明了一个参数为两个int类型,返回值为int类型的指针的函数,而不再是一个函数指针了。


在经常使用函数指针之后,我们很快就会发现,每次声明函数指针都要带上长长的形参和返回值,非常不便。这个时候,我们应该想到使用typedef,即为某类型的函数指针起一个别名,使用起来就方便许多了。例如,对于前面提到的函数可以使用下面的方式声明:


上面的myFun就是一个函数指针类型,在其他地方就可以很方便地用来声明变量了。typedef的使用不在本文的讨论范围,但是特别强调一句,typedef中声明的类型在变量名的位置出现,理解了这一句,也就很容易使用typedef了。因而下面的方式是错误的:


赋值也很简单,既然是指针,将对应指针类型赋给它既可。例如:


在这里,声明了返回类型为int,接受两个int类型参数的函数指针f1和f2,分别给它们进行了赋值。表达式1和表达式2在作用上并没有什么区别。因为函数名在被使用时总是由编译器把它转换为函数指针,而前面加上&不过显式的说明了这一点罢了。


调用也很容易,把它看成一个普通的函数名即可:


在函数指针后面加括号,并传入参数即可调用,其中表达式1和表达式2似乎都可以成功调用,但是哪个是正确的呢?ANSI C认为这两种形式等价。


函数指针的应用场景比较多,以库函数qsort排序函数为例,它的原型如下:


看起来很复杂对不对?拆开来看如下:


拿掉第四个参数后,很容易理解,它是一个无返回值的函数,接受4个参数,第一个是void*类型,代表原始数组,第二个是size_t类型,代表数据数量,第三个是size_t类型,代表单个数据占用空间大小,而第四个参数是函数指针。这第四个参数,即函数指针指向的是什么类型呢?


很显然,这是一个接受两个const void*类型入参,返回值为int的函数指针。
到这里也就很清楚了。这个参数告诉qsort,应该使用哪个函数来比较元素,即只要我们告诉qsort比较大小的规则,它就可以帮我们对任意数据类型的数组进行排序。


在这里函数指针作为了参数,而他同样可以作为返回值,创建数组,作为结构体成员变量等等,它们的具体应用我们在后面的文章中会介绍,本文不作展开。本文只介绍一个简单实例。


我们通过一个实例来看函数指针怎么使用。假设有一学生信息,需要按照学生成绩进行排序,该如何处理呢?


我们创建了一个学生信息结构,结构成员包括名字,学号和成绩。main函数中创建了一个包含三个学生信息的数组,并使用qsort函数对数组按照学生成绩进行排序。qsort函数第四个参数是函数指针,因此我们需要传入一个函数指针,并且这个函数指针的入参是cont void *类型,返回值为int。我们通过前面的学习知道了函数名本身就是指针,因此只需要将我们自己实现的studentCompare作为参数传入即可。


最终运行结果如下:


可以看到,最终学生信息按照分数从低到高输出。


本文介绍了函数指针的声明和简单使用。更多使用将在后面的文章介绍,本文总结如下:


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C语言谁是窃贼问题代码及解析 下一篇GDB调试指南-启动调试

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目