`
yuanlanjun
  • 浏览: 1187871 次
文章分类
社区版块
存档分类
最新评论

浅谈函数指针

 
阅读更多

函数指针的概念,在潭浩强先生的C语言程序设计这本经典的教程中提及过,在大多数情况下我们使用不到,也忽略了它的存在。函数名实际上也是一种指针,指向函数的入口地址,但它又不同于普通的如int*、double*指针,看下面的例子来理解函数指针的概念:

第一行代码首先定义了一个函数function,其输入为两个整型数,返回也为一个整型数(输入参数和返回值可为其它任何数据类型);后面又定义了一个函数指针fun,与int*或double*定义指针不同的是,函数指针的定义必须同时指出输入参数,表明这是一个函数指针,并且*fun也必须用一对括号括起来;并将函数指针赋值为函数function,前提条件是*fun和function的输入参数和返回值必须保持一致,否则无法通过编译。可以直接调用函数function(),也可以直接调用函数指针,二者是等效的。

声明函数指针

回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。请看下面的例子:

void f(); // 函数原型

上面的语句声明了一个函数,没有输入参数并返回void。那么函数指针的声明方法如下:

void (*) ();

函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢?

如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。

定义一个指向函数的指针用如下的形式,以上面的test()为例:

int (*fp)(int a); //这里就定义了一个指向函数的指针

函数指针绝对不能指向不同类型,或者是带不同形参的函数,在定义函数指针的时候我们很容易犯如下的错误。

int *fp(int a); //这里是错误的,因为按照结合性和优先级来看就是先和()结合,然后变成了一个返回整形指针的函数了,而不是函数指针,这一点尤其需要注意!

例如函数原型为:

int fun(int *, int);

则函数指针可以声明为: int (*pf)(int *, int);
当然从上述例子看不出函数指针的优点,目的主要是想引出函数指针数组的概念。我们从上面例子可以得知,既然函数名可以通过函数指针加以保存,那们也一定能定义一个数组保存若干个函数名,这就是函数指针数组。正确使用函数指针数组的前提条件是,这若干个需要通过函数指针数组保存的函数必须有相同的输入、输出值。

如果赋了不同的值给函数指针,那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。

下面我们来看一个具体的例子:

typedef定义可以简化函数指针的定义,在定义一个的时候感觉不出来,但定义多了就知道方便了,上面的代码改写成如下的形式:




分享到:
评论

相关推荐

    浅谈在Swift中关于函数指针的实现

    主要介绍了浅谈在Swift中关于函数指针的实现,是作者根据C语言的指针特性在Swifft中做出的一个实验,需要的朋友可以参考下

    浅谈C语言中函数形参为指针类型的参数传递.pdf

    浅谈C语言中函数形参为指针类型的参数传递.pdf

    应用笔记LAT1241+浅谈STM32库里的回调函数

    有人对 STM32 固件库里的回调函数有些好奇甚至纠结,这里...一般来讲,所谓回调函数,泛指基于事件触发而被调用执行的函数,简单点说,就是条件满足了就调用的函数,往往会跟函数指针结合起来通过函数指针实现调用。

    浅谈关于指针作为参数并改变它的值的问题

    代码如下:#include...//指针p是首地址 f(p);//调用 printf(“%d”,*p);//p的值是不会改变的 } 结果:21Press any key to continue 代码如下:#include<stdio> void z(int *p){ p = p+1; *p = 100; } void mian(){

    浅谈C++指针(必看)

    指针在编程中有时很重要的作用 我们可以用它完成一些看似不可能完成的任务 #include using namespace std; void square(int *n){ *n=*n**n; } int main(){ int num = 2; cout<<The original number is <&...

    浅谈JavaScript 函数参数传递到底是值传递还是引用传递

    在传统的观念里,都认为JavaScript函数传递的是引用传递(也称之为指针传递),也有人认为是值传递和引用传递都具备。那么JS的参数传递到底是怎么回事呢?事实上以下的演示也完全可以用于Java 首先来一个比较简单的,...

    浅谈C++ 基类指针和子类指针的相互赋值

    // describe: 非虚函数情况下,将子类指针赋给积累指针,验证最终调用 // 基类函数还是子类函数。 //============================================================== #ifndef ANIMAL_H #define ANIMAL_H //======...

    浅谈C++中虚函数实现原理揭秘

    通过基类指针做虚函数调 用时(也就是做多态调用时),编译器静态地插入取得这个V P T R,并在V TA B L E表中查找函数地址的代码,这样就能调用正确的函数使晚捆绑发生。为每个类设置V TA B L E、初始化V P T R、为...

    浅谈iOS 对于block的一点理解

    它和传统的函数指针很类似,但是有区别:block是inline的,并且它对局部变量是只读的。 Block的定义: int (^myBlock) (int a,int b) = ^(int a,int b){ return a+b; };  定义了一个名为myBlock的blocks对象...

    浅谈C++ 虚函数分析

    虚函数调用属于运行时多态,在类的继承关系中,通过父类指针来调用不同子类对象的同名方法,而产生不同的效果。 C++ 中的多态是通过晚绑定(对象构造时)来实现的。 用法 在函数之前声明关键字 virtual 表示这是一个...

    浅谈js中调用函数时加不加括号的问题

    不加括号的,都是把函数名称作为函数的指针,用于传参,此时不是得到函数的结果,因为不会运行函数体代码。它只是传递了函数体所在的地址位置,在需要的时候好找到函数体去执行。 所以一般时候我们都是采用的是无...

    浅谈C++基类的析构函数为虚函数

     在实现多态时, 当用基类指针操作派生类, 在析构时候防止只析构基类而不析构派生类。 2、例子:  (1)、    #include  using namespace std;  class Base{  public: Base() {};  ~Base() {cout <&...

    浅谈javascript 函数内部属性

     但是这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。  请看经典的阶乘函数例子: 代码如下:  function Factorial(num) {  if (num <= 1) {  return 1;  } else ...

    浅谈python函数调用返回两个或多个变量的方法

    以元祖形式返回 return (a,b,……) 以元祖引用或(x,y,….)接受都...以上这篇浅谈python函数调用返回两个或多个变量的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持软件开发网。

    浅谈C++ 虚函数

    本文将简单探究一下 c++ 中的虚函数实现机制。本文主要基于 vs2013 生成的 32 位代码进行研究,相信其它编译器(比如,gcc)的实现大同小异。 先从对象大小开始 假设我们有如下代码,假设 int 占 4 字节,指针占 4 ...

    浅谈JavaScript中的this指针和引用知识

    this指针在传统OO语言中,是在类中声明的,表示对象本身.在JavaScript中,this表示当前上下文,即调用者的引用 ********this永远指向的是(函数对象)的所有者 this和全局对象: var a = 1; function foo(){ var b = 2; ...

    浅谈JavaScript中指针和地址

    个人理解:指针只是指向内存的一个索引;而地址则是内存中确切的位置。... 注意:使用不带圆括号的函数的名是访问函数指针,而非调用函数,所以 sum和anotherSum指向同一个函数,即 sum=null;不影响anotherSum

    浅谈c/c++中使用指针需要注意的问题

    如果指针p是函数的参数,那么在函数的入口处用assert(p != NULL)进行检查。如果使用malloc或new来申请内存,应该用if(p == NULL)或if(p != NULL)进行放错处理。 2)内存分配虽然成功,但是尚未初始化就引用它 犯这种...

    浅谈Javascript中的函数、this以及原型

    在Javascript中函数实际上就是一个对象,具有引用类型的特征,所以你可以将函数直接传递给变量,这个变量将表示指向函数“对象”的指针,例如: function test(message){ alert(message); } var f = ...

    浅谈西门子Prodave6.0在C#中的应用

    比如 char* 可以用string来转换,指针类型可以ref 或者数组。 原文地址:http://www.cnblogs.com/xumingming/archive/2008/10/10/1308248.html 二.定义结构体类型 2.1 PLC连接参数结构体 1//定义结构体[连接PLC所需...

Global site tag (gtag.js) - Google Analytics