非典型性C语言教程-1.5 函数指针
2007-07-15 16:03
344 查看
函数指针是非常重要的概念,后来的对象概念都依赖与函数指针的概念,比如C++对象的虚函数指针表,比如Java的接口,比如.Net的委托机制。
函数指针就是函数的入口地址。它的定义形式如下:
int (*pfun)(int);
这里定义了一个函数指针叫pfun,它指向的函数应该是有一个惨呼类型int,返回值是int。虽然C语言的函数指针可能带类型信息,但是这个类型信息没有什么很大用处,实际上整个C语言都没有什么类型信息,你可以在运行时很简单的改变C语言的类型信息。比如函数指针:
int (*pfun)(int);
你 可以把它指向标准函数printf。显然printf的函数类型是int (*printf)(char*,...);而不是int(*pfun)(int);。C语言不会帮你进行类型检查,但是如果你把指针pfun指向 printf,然后通过pfun来调用printf会是一个未定义行为,未定义一般意味着程序崩溃。
这么定义函数指针的语法有点麻烦,当函数的申明很复杂时,会定义出一个很难看懂的东西,比如:
int* (*(*pfun)(int*))(int*);
这种定义就让人难以理解。合理的运用C语言的typedef特性就可以让函数指针的定义变得明确,提高代码的可读性。比如上面的定义我们首先定义:
typedef int* (*PFUN_1)(int*);
这样我们就定义了一个别名PFUN_1,PFUN_1是一个函数指针的类型,这种函数指针指向的函数有一个参数是int*,返回类型是int*。这样:
int* (*(*pfun)(int*))(int*);
就可以简化为:
PFUN_1 (*pfun)(int*);
即一个函数指针pfun它指向的函数的返回类型是一个PFUN_1,函数的参数是一个int*。同理可以进一步简化,定义typedef:
typedef PFUN_1 (*PFUN_2)(int*);
然后把pfun的定义简化为
PFUN_2 pfun;
Unix 中系统调用signal,就是一个参数是函数指针,返回值是函数指针的函数,它的定义就比较难懂。在Windows中动态加载DLL的API函数 GetProcAddress返回的也是一个函数指针,通常需要定义一个typedef,不然使用GetProcAddress的代码也是晦涩难懂。
使用函数指针就和使用函数基本是一样的。比如
pfun(&a);
为什么要用函数指针能,函数指针主要的用途就在OO编程中的多态。C++是OO语言,C语言不是,但是用C可以实现多态,C++实现多态的原理也是C的函数指针。
举个例子,C语言的标准库中有一个函数qsort。这个函数的申明是:
大家知道C语言是没有重载和模板机制的,如果你要写一个求两个数字中大的一个的函数,你必须写一个
short,char,int等类型都可以自动转换成double。但是如果你需要一个自定义的复数类型
上 面这个函数就不好用了。排序函数也是一样,标准排序函数大部分内容都是一样的,选出枢轴,比较交换,递归,但是不同的数据元素有不同的比较方法。比如刚才 的复数,简单的用关系运算符就无法比较。为了写一个通用的快速排序版本,标准库的作者用了两个技巧。第一个就是void类型的指针,void类型可以指向 任何内存地址,只要参数width给出指向一个数据元素的大小就可以了。第二个就是函数指针int (__cdecl *compare )(const void *, const void *),对于你自己定义的复合类型,你需要定义一个函数来进行比较,然后把这个函数通过指针的形式告诉标准库函数qsort,qsort就知道如何对数据类 型排序了。
比如现在我有一个复合类型struct complex的数组struct complex cAarray[100];我需要将它按模的大小排序。首先我要定义函数compare:
然后调用函数qsort:
qort(cArray, 100, sizoef(struct complex), compare );
实际上函数指针可以更改另一个函数的行为,这是它最重要的作用。
函数指针就是函数的入口地址。它的定义形式如下:
int (*pfun)(int);
这里定义了一个函数指针叫pfun,它指向的函数应该是有一个惨呼类型int,返回值是int。虽然C语言的函数指针可能带类型信息,但是这个类型信息没有什么很大用处,实际上整个C语言都没有什么类型信息,你可以在运行时很简单的改变C语言的类型信息。比如函数指针:
int (*pfun)(int);
你 可以把它指向标准函数printf。显然printf的函数类型是int (*printf)(char*,...);而不是int(*pfun)(int);。C语言不会帮你进行类型检查,但是如果你把指针pfun指向 printf,然后通过pfun来调用printf会是一个未定义行为,未定义一般意味着程序崩溃。
这么定义函数指针的语法有点麻烦,当函数的申明很复杂时,会定义出一个很难看懂的东西,比如:
int* (*(*pfun)(int*))(int*);
这种定义就让人难以理解。合理的运用C语言的typedef特性就可以让函数指针的定义变得明确,提高代码的可读性。比如上面的定义我们首先定义:
typedef int* (*PFUN_1)(int*);
这样我们就定义了一个别名PFUN_1,PFUN_1是一个函数指针的类型,这种函数指针指向的函数有一个参数是int*,返回类型是int*。这样:
int* (*(*pfun)(int*))(int*);
就可以简化为:
PFUN_1 (*pfun)(int*);
即一个函数指针pfun它指向的函数的返回类型是一个PFUN_1,函数的参数是一个int*。同理可以进一步简化,定义typedef:
typedef PFUN_1 (*PFUN_2)(int*);
然后把pfun的定义简化为
PFUN_2 pfun;
Unix 中系统调用signal,就是一个参数是函数指针,返回值是函数指针的函数,它的定义就比较难懂。在Windows中动态加载DLL的API函数 GetProcAddress返回的也是一个函数指针,通常需要定义一个typedef,不然使用GetProcAddress的代码也是晦涩难懂。
使用函数指针就和使用函数基本是一样的。比如
pfun(&a);
为什么要用函数指针能,函数指针主要的用途就在OO编程中的多态。C++是OO语言,C语言不是,但是用C可以实现多态,C++实现多态的原理也是C的函数指针。
举个例子,C语言的标准库中有一个函数qsort。这个函数的申明是:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *, const void *) );
大家知道C语言是没有重载和模板机制的,如果你要写一个求两个数字中大的一个的函数,你必须写一个
double max(double x, double y) { return x>y?x:y; }
short,char,int等类型都可以自动转换成double。但是如果你需要一个自定义的复数类型
struct complex { double real; double img; }
上 面这个函数就不好用了。排序函数也是一样,标准排序函数大部分内容都是一样的,选出枢轴,比较交换,递归,但是不同的数据元素有不同的比较方法。比如刚才 的复数,简单的用关系运算符就无法比较。为了写一个通用的快速排序版本,标准库的作者用了两个技巧。第一个就是void类型的指针,void类型可以指向 任何内存地址,只要参数width给出指向一个数据元素的大小就可以了。第二个就是函数指针int (__cdecl *compare )(const void *, const void *),对于你自己定义的复合类型,你需要定义一个函数来进行比较,然后把这个函数通过指针的形式告诉标准库函数qsort,qsort就知道如何对数据类 型排序了。
比如现在我有一个复合类型struct complex的数组struct complex cAarray[100];我需要将它按模的大小排序。首先我要定义函数compare:
int compare (const void * _l, const void * _r) { struct complex* pl=_l; struct complex* pr=_r; double ml= pl.real*pl.real+pl.img*pl.img; double mr= pr.real*pr.real+pr.img*pr.img; if(ml>mr)return 1; if(ml==mr)return 0; if(ml
然后调用函数qsort:
qort(cArray, 100, sizoef(struct complex), compare );
实际上函数指针可以更改另一个函数的行为,这是它最重要的作用。
相关文章推荐
- 非典型性C语言教程-1.2 函数
- 非典型性C语言教程-1.4 指针,字符串,数组
- C语言基础-函数、指针
- Swift3.0语言教程使用指针创建和初始化字符串
- c 语言函数传参的三种方式及二级指针的理解
- C/C++语言中指向函数的指针
- 【C语言基础】对指针数组,数组指针,函数指针, 函数指针数组,指向函数指针数组的指针的理解
- c语言 - 指针作为函数参数
- C语言教程第六章:指针
- 函数指针2017/12/2C语言学习内容总结
- Virtools脚本语言(VSL)教程 - 函数
- C语言基础:函数指针
- C语言指针导学(4)——分清函数指针和指针函数收藏
- 20151215C语言基础16_函数3(数组与指针)
- 非典型性C语言教程- 1.6 结构,共用体,常量和typedef
- Swift2.0语言教程之Swift2.0语言中的标准函数
- 11.17C程序设计语言---字符指针与函数
- 第四周《C语言及程序设计》实践项目7 返回指针的函数
- 关于C语言中一,二级指针函数中的使用和c语言中和函数发生调用时,实参和形参都会占用内存吗?
- 非典型性C语言教程-1.1 变量