C函数指针的偏门作用
C语言的指针不仅可以指向数据域,也可以指向一个函数。很多C的初学者并不清楚这个特性,在看一些源代码的时候常常会觉得困惑。
C的函数最常用的是提供函数Callback的能力,比如,C的”stdlib”中声明的qsort函数,用来对数值进行排序。显然,顺序还是降序,元素谁大谁小这些问题,库程序员在编写qsort的时候不可能决定。这些问题是要在用户调用这个函数的时候才能够决定。那边qsort如何保证通用性和灵活性呢?采用的办法是让函数的使用者来制定排序规则。qsort的声明如下:
void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );
其中
int ( * comparator ) ( const void *, const void * )
便是一个函数指针,指向某个用户自定义的比较函数。参考C++ Reference的例子如下:
/* qsort example */ int values[] = { 40, 10, 100, 90, 20, 25 }; int compare (const void * a, const void * b) { return ( *(int*)a - *(int*)b ); } int main () { int n; qsort (values, 6, sizeof(int), compare); for (n=0;n<6; n++) printf ("%d ",values[n]); return 0; }
除了提供回调的能力之外,C函数指针也有其他有趣的用途,比如,利用它来进行面向对象式的编程,比如,利用它来避免C名字空间的冲突。
参考上文,我提供的stack结构体的定义如下
typedef struct easyc_stack{ int base_size; int point; int * base; int size; int (*pop)(struct easyc_stack *); int (*push)(int,struct easyc_stack *); int (*get_top)(struct easyc_stack ); }c_stack;
在初始化完之后,用户调用这个结构体上的pop函数,只需要 s.pop(&s)即可。即使这个时候,工程内部有另外一个函数名字也叫pop,他们之间是不会发生名字上的冲突的。原因很简单,因为结构体中的函数指针pop指向的函数名字可能是
int ugly_stupid_no_one_will_use_this_name_pop(c_stack *)
,只是stack的用户是不知道他在调用s.pop(&s),实际上起作用的是这样一个有着冗长名字的函数。
函数指针这种避免命名冲突上的额外好处对于一些库函数的编写者是很有意义的,因为库可能被很多的用户在许多不同的环境下使用,这样就能有效的避免冲突而保证库的可用性。
认领 BANGD2569BE2B2E8A4BC39F1189CXIANGUO






8 个评论 关于 “C函数指针的偏门作用”
By 风吟 on Aug 24, 2008 |
我觉得 C++和php很有相似之处。
陈炬 回复说:
August 24th, 2008 at 7:09 pm
恩,php设计的时候就参照了C的语法吧~~
By zamanewby on Aug 26, 2008 |
C快忘干净了, C++完全不会…
前些日子看信号那块还琢磨半天函数指针。
void (*signal(int signo, void (*func)(int)))(int);
为这一个声明翻了C Primer Plus, 然后想了半天才明白-___-#
陈炬 回复说:
August 26th, 2008 at 12:09 am
这个例子里有函数指针作为参数以回调,qsort的定义也类似吧。
记得关于函数指针有个经典的例子 (*(void (*)( ) )0)( )
c++我也完全不懂…
C Primer Plus这书好么?
By zamanewby on Aug 26, 2008 |
当时万涛推荐我看的。 入门级别的, 但比国内教材要好。
陈炬 回复说:
August 26th, 2008 at 12:19 am
我C入门是看那本K&R C程序设计语言的.
之后看过C专家编程,没有细看,最近想细看,发现书丢了,真郁闷。
zamanewby 回复说:
August 26th, 2008 at 12:25 am
恩, 听说了C专家编程不错, 我还想买一本呢
陈炬 回复说:
August 26th, 2008 at 12:32 am
那书不错,不厚,装订也很精美。内容也很好。