`

c 函数指针

 
阅读更多
函数指针是什么?
    先来看函数调用是怎么回事。一个函数占用一段连续内存。当调用一个函数时,实际上是跳转到函数入口地址,执行函数体的代码,完成后返回。如何找到对应的入口地址?这是由函数名来标记的,实际上,函数名就是函数的入口地址。
    函数指针是一种特殊类型的指针,它指向一个函数的入口地址。

    注意:除了void类型指针是无类型的指针外,其他所有指针都是有对应类型的,例如int *pint、struct studentdata *psdata等,只有指明了指针所指的数据类型,编译器才能为指针分配或预计分配相应大小的存储空间,指针的算术运算如pint++等才是有意义的。因此,定义了某种类型的指针之后,除非使用强制类型转换,那么它只能指向相应数据类型的变量或常量,不同类型的指针或数据之间不可混用。所以指针的类型实际上是一种身份标志的作用。

   函数指针如何表明自己的身份呢?为了避免混乱,必须也要作出相应规定,不同函数的函数指针不能混用。例如,int func1(int arg11, char arg12)与int func2(char arg)的函数指针就不能混用,要定义可以指向func1的函数指针应该这样:
    int (*pfunc1)(int, char) = func1;
定义可以指向func2的函数指针则该如下:
    int (*pfunc2)(char) = func2;
    从函数指针的定义可以看出,函数指针的类型实际上是由函数签名决定的。函数签名就象是函数的身份证,一个函数的函数签名是独一无二的,具有相同函数签名的函数实际上就是同一函数。函数签名包括函数名、函数形参类型的有序列表和函数返回值类型。

    一个函数指针的定义规定了它只能指向特定类型的函数。如果两个函数的形参列表和返回值类型相同,只有函数名和函数体不同,则可以使用相同类型的函数指针。例如,如果还有一个函数int func3(char arg),则上面定义的可以指向函数func2的函数指针也可以用于指向func3,即:
    pfunc2 = func3;
    再使用pfunc2(char ARG)就可以调用函数func3,这时指令计数器(PC)指向函数入口,从此开始执行函数体代码。
    注意:对函数指针进行算术运算也是没有意义的。

如何使用函数指针?
    ①定义合适类型的函数指针变量;
       int (*pfunc)(int, int);
    ②给函数指针变量赋值,使它指向某个函数入口;
       int example(int, int);
       pfunc = example;          /*将函数入口地址赋给函数指针变量*/
       或者:pfunc = &example;    /*函数名总是被编译器转换为函数指针(入口地址)来使用,因此与上面一句等价 */
    ③使用函数指针来调用相应的函数;
       retval = pfunc(10, 16);
       或者:retval = (*pfunc)(10, 16);
       上面两句都与retval = example(10, 16);等价。
    理解:一个指针变量p实际上也和普通的变量一样,要占存储空间(通常与平台的虚拟地址一样宽),也有其自身的存储地址&p;不同的是,在指针变量 p的值有特殊的意义,它是另外一个变量或常量的地址值,也就是说,在地址为&p的存储单元上存放着另外一个数据的地址。因此,*p实际上是将p看作它指向的数据的地址来使用,*操作符是引用相应地址中的数据,也就是对地址为p的存储单元中存放的数据进行操作。
    一个函数指针变量则更为特殊。比如上面的例子,pfunc变量本身的值是函数example()的入口地址。因此pfunc可以代替其所指函数的函数名来使用。至于*pfunc,如果按照上面的理解,它实际上是地址pfunc的内容,也即函数example()的入口地址的内容,就有点含糊了。不过,从另一方面来理解,如果使用pfunc = &example来初始化pfunc,则*pfunc == *(&example) == example,又与pfunc等价。因此,就有了两种使用函数指针来调用相应函数的形式。
    值得注意的是,不可用*pfunc来对pfunc的值初始化。即*pfunc = example的写法是错误的。

为什么要使用函数指针?
    前面介绍了函数指针的基本知识和使用规范。下面介绍函数指针的实际用途。不过首先要对前面的知识再做一个补充,因为下面的应用很可能用到这一特性。前面指出,除函数名之外的函数签名内容(函数返回值类型和形参列表)决定了函数指针的类型。实际上还有一种特殊的或说通用的函数指针,在定义这类函数指针时,只需要指定函数返回值类型,而留空形参列表,这样就可以指向返回值类型相同的所有函数。例如:
    int (*pfunc)();
    这样定义的pfunc就可以指向前面提到的func1和func2,因为他们都返回整型值。
    注意: int (*pfunc)()与int (*pfunc)(void)不是一回事,后者不允许接受任何参数。

    函数指针最常见的三个用途是:
    ①作为参数传递给其他函数。
    这样可以把多个函数用一个函数体封装起来,得到一个具有多个函数功能的新函数,根据传递的函数指针变量值的不同,执行不同的函数功能。这是函数嵌套调用难以实现的。参数的传递可以由程序员设定,也可以由用户输入读取,因此具有较大的灵活性和交互性。
    另外还可以用于回调函数。使用void配合,还可以将对不同数据类型的数据进行相同处理的多个函数封装为一个函数,增强函数的生命力。

    ②用于散转程序。
    这种程序首先建立一个函数表(实际上是一个函数指针数组),表中存放了各个函数的入口地址(或函数名),根据条件的设定来查表选择执行相应的函数。这样也可以将多个函数封装为一个函数或者程序,散转分支条件可以由程序员设定,也可以由用户输入读取,甚至是外设的某种特定状态(这种状态可以是不受人为控制的)。

    ③实现C的面向对象的类的封装。
    C语言中的struct与C++中的class有很大不同,除了缺省的成员属性外(struct的成员缺省为public的,可随意使用,而class成员缺省为private的),struct还很难实现类成员函数的封装。struct的成员一般都是数据成员,而非函数成员。因此,为了在C语言中,为某个struct定义一套自己的函数对结构数据成员进行操作,可以在struct结构体中增加函数指针变量成员,在初始化时使它指向特定函数即可。

    应用举例:
    ①假设定义了四个函数:add(int, int)、sub(int, int)、mul(int, int)、div(int, int),可以将其封装为一个四则运算计算器函数:
    double calculator(int x, int y, int (*pfunc)(int, int)) {
       double result;
       result = pfunc(x, y);
       return result;
    }
    又例如,在一个链表查询程序中,要通过比较节点的特征值来查询节点,不同类型的数据的比较方式不一样,整型等可以直接比较,字符串却要用专门的字符串操作函数,为了使代码可重用性更高,可以使用一个比较函数来代替各种不同数据类型的直接比较代码,同时,比较函数也必然是数据类型相关的,因此要使用void 指针和函数指针来转换为类型无关的比较函数,根据相应的数据类型,调用相应的函数(传递相应的函数指针)。一个实例是:
    int (*compare)(void const *, void const *);
    这个函数指针可以接受任意类型的数据的指针参数,同时返回int值作为比较结果标志。一个比较整型数据的比较函数是:
    int compare_ints(void const *a, void const *b) {
       if( *(int *)a == *(int *)b )
          return 0;
       else
          return 1;
    }

    ②散转程序。通过一个转移表(函数指针数组)来实现。还是上面定义的四个四则运算函数,可以建立这样一个转移表(注意初始化该转移表的语句前面应有add等相应函数原型声明或定义):
    double (*calculator[])(int, int) = {
       add, sub, mul, div
    };
    这样,calculator[0] == add, calculator[1] == sub, ...
    使用result = calculator[oper](x, y);就可以代替下面整个switch语句:
    switch( oper ) {
       case 0: result = add(x, y); break;
       case 1: result = sub(x, y); break;
       ...
    }

    ③C的面向对象化。一个对象包括数据和对数据的操作。C语言中的struct只有数据成员,因此要增加一些“伪数据成员”即函数指针来实现对数据的操作。例如:
    #ifndef C_Class
    #define C_Class struct
    #endif
    C_Class student{
       C_Class student *student_this
       char name;
       int height;
       int gender;
       int classnum;
       ...
       void (*Oper)( C_Class student *student_this );
       ...
    }

原文地址:http://blog.chinaunix.net/u/26710/showart_209517.html

照上面的我自己写了个酷点的^_^

typedef struct {
  char *name;        /* User printable name of the function. */
  Function *func;    /* Function to call to do the job. */
  char *doc;        /* Documentation for this function. */
} COMMAND;

COMMAND commands[] = {
  { "cd", com_cd, "Change to directory DIR" },
  { "delete", com_delete, "Delete FILE" },
  { "help", com_help, "Display this text" },
  { "?", com_help, "Synonym for `help'" },
  { "list", com_list, "List files in DIR" },
  { "ls", com_list, "Synonym for `list'" },
  { "pwd", com_pwd, "Print the current working directory" },
  { "quit", com_quit, "Quit using Fileman" },
  { "rename", com_rename, "Rename FILE to NEWNAME" },
  { "stat", com_stat, "Print out statistics on FILE" },
  { "view", com_view, "View the contents of FILE" },
  { (char *)NULL, (Function *)NULL, (char *)NULL }
};

使用的时候:
COMMAND *command;
(*(command->func)) (word)
分享到:
评论

相关推荐

    C语言函数指针.doc

    一、函数指针的定义 顾名思义,函数指针就是函数的指针。它是一个指针,指向一个函数。看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun2(char * p1,char * p2); C) char * fun3(char * p1,char * ...

    C语言函数指针小结C语言函数指针小结.doc

    C语言函数指针小结 C语言函数指针是C语言中一个重要的组成部分,使用函数指针编程有以下优点: 1. 提高程序的编译效率和执行速度。 2. 通过函数指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现...

    c语言函数指针和指针函数.pdf

    函数指针是 C 语言中的一种特殊的指针,它可以指向函数的地址,而不是变量的地址。函数指针的定义格式为:`返回类型 (*指针变量名)(参数列表)`,其中返回类型是函数的返回类型,指针变量名是函数指针的名称,参数...

    C语言函数指针复习小结

    以下是对C语言函数指针的详细说明: 1. **指针基础**: - 指针是C语言的核心部分,它可以存储内存地址,使得我们能直接操作内存。 - 指针的运算包括取地址运算符`&`,取内容运算符`*`,赋值运算,加减运算以及...

    C语言函数指针实现心得案例

    在这个“C语言函数指针实现心得案例”中,我们将探讨如何使用函数指针来实现不同的排序算法,如冒泡排序、选择排序、插入排序和快速排序。通过Visual Studio 2017 (VS2017) 的控制台项目,我们可以直观地了解这些...

    C语言指针函数和函数指针详细介绍.

    C语言指针函数和函数指针详细介绍 C语言中指针函数和函数指针是两个不同的概念,但它们之间存在着紧密的联系。本文将对C语言中的指针函数和函数指针进行详细的介绍。 一、指针函数 指针函数是指返回值为指针的...

    C语言函数指针与指针函数训练.zip

    在C语言中,函数指针和指针函数是高级特性,它们在编程中扮演着重要角色,尤其是在处理回调函数、动态调度以及实现元编程等方面。本训练将深入讲解这两个概念,帮助你掌握其核心概念和实际应用。 首先,我们要了解...

    C语言函数指针[文].pdf

    C语言函数指针 函数指针是一种特殊的指针,它指向一个函数。函数指针可以用来实现函数的间接调用,并且可以将实现同一功能的多个模块统一起来标识,提高系统的维护性和可读性。 一、函数指针的定义 函数指针的...

    C语言函数指针

    【C语言函数指针】是C语言中一种高级特性,它允许我们将函数的地址作为其他函数的参数,或者存储在变量中,以便后续调用。理解函数指针是深入掌握C语言的重要步骤。 首先,我们要了解函数在C语言中的本质。在C语言...

    C语言 函数指针分析

    ### C语言中的函数指针详解 #### 一、引言 在C语言中,函数指针是一种非常重要的概念,它允许我们将函数作为一种数据类型来处理。通过使用函数指针,我们可以更加灵活地控制程序的执行流程,实现回调函数、动态...

    c语言函数指针和指针函数[收集].pdf

    c语言函数指针和指针函数[收集].pdf

    学习c语言函数指针和指针函数.pdf

    C语言中的函数指针和指针函数是两个关键概念,它们允许我们以更灵活的方式处理函数,实现回调机制、动态绑定以及在运行时决定调用哪个函数等功能。 1. **函数指针**: - 函数指针是一种特殊的指针变量,它存储的是...

    课程思政促进C语言函数指针教学的实践.pdf

    课程思政促进C语言函数指针教学的实践

    函数指针的详解

    ### 函数指针详解 ...函数指针是C语言中一个重要的概念,它提供了更大的灵活性和扩展性,使得程序员可以编写更加高效和模块化的代码。正确理解和掌握函数指针的使用对于提高编程水平具有重要意义。

    C语言中关于函数指针的用法

    ### C语言中关于函数指针的用法 在C语言中,函数指针是一种非常强大的特性,它允许程序员将函数当作参数传递给其他函数或在运行时决定调用哪个函数,这种灵活性对于实现某些高级算法(如排序算法中的比较函数)至关...

    指针函数和函数指针变量

    在C语言中,指针和函数是两个非常重要的概念,而将它们结合在一起,就产生了指针函数和函数指针变量。这两个概念是C语言高级特性的体现,它们在编程中有着广泛的应用,如回调函数、动态加载库、内存管理等。 首先,...

    C语言 函数指针(指向函数的指针)详解

    在C语言中,函数指针是一种强大的特性,它允许我们存储函数的地址并直接通过指针调用函数,使得在程序中动态地决定执行哪个函数成为可能。下面将详细讲解函数指针的概念、定义方式、使用方法以及示例。 1. **函数...

    笔记_嵌入式Linux_C_函数指针

    总的来说,函数指针在嵌入式Linux的C编程中扮演着重要角色,它可以用来实现回调机制、策略模式、函数工厂等高级设计模式,提高代码的可维护性和可扩展性。通过理解和熟练运用函数指针,开发者可以编写更加灵活和高效...

Global site tag (gtag.js) - Google Analytics