C语言有一个很屌的功能,但是又有点难以整明白的东西,叫函数指针,每个函数都有一个物理地址,这个地址可以赋给一个指针,这个地址就是函数的入口点,当一个指针指向某个函数的时候,通过这个指针,我们就能调用这个函数,函数指针的出现,使得函数可以作为一参数传递给另一个函数。
那怎样去获取到一个函数的地址呢? 很简单,函数名,不加任何参数或者括号,和攻取数组的地址是一致的,只需要给出数组名就可拿到数组的起始地址。想要了解这个具体是怎么做,可以看看下面这个程序,这个程序去比较两个由用户输入的字符串,请用心看看 函数check 的声明 ,以及指针p 的声明。
#include <stdio.h>
#include <string.h>
void check(char *a, char *b, int (*cmp)(const char *, const char *));
int main(void)
{
char s1[80], s2[80];
int (*p) (const char *, const char *); /* function pointer */
p = strcmp; /* assign address of strcmp to p */
printf("Enter two strings.\n");
gets(s1);
gets(s2);
check(s1, s2, p); /* pass address of strcmp via p */
return 0;
}
void check(char *a, char *b, int (*cmp) (const char *, const char *))
{
printf("Testing for equality.\n");
if (!(*cmp)(a, b)) printf("Equal");
else printf("Not Equal");
}
下面我们来仔细分析这个程序,首先看一哈在main 函数中p的声明,
int (*p)(const char *, const char *);
这个声明告诉编译器,p是一个指向函数的指针,这个函数具有两个const char * 参数,返回值为int. 注意这两边的括号是必不可少的,以后再声明其他含数指针的时候,也要像介个样子。
再来,仔细分析check() 函数,它声明了三个参数,两个字符型指针,a 和b.还有一个函数指针 cmp. 细心的你一定会注意到它的声明格式和main()函数里面的p是一样一样的。
和p的声明一样,*cmp 两边的括号是不能少的, cmp 像这个声明,使用它可以获取一个这样的函数指针。
当这个程序跑起来的时候,它会将strcmp() 的地址赋给p, strcmp 是标准库提供的比较函数,然后,提示用户输入两个strings, 然后连同p一起传给check.
在check 里面
(*cmp) (a, b)
会去调用 strcmp(), cmp 指向了strcmp, 并且带个两个参数,a 和b, 同样的 *cmp 两边的括号是不能少的,这是一种通过指针去调用函数的方式,第二种,一种简单的写法也可以
cmp(a,b);
大部分情况下会使用第一种风格,这样别人在阅读代码的时候,就可以知道,这是通过函数指针去调用一个函数,
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
void check(char *a, char *b, int (*cmp)(const char *, const char *));
int compvalues(const char *a, const char *b);
int main(void)
{
char s1[80], s2[80];
printf("Enter two values or two strings.\n");
gets(s1);
gets(s2);
if (isdigit(*s1)) {
printf("Testing values for equality.\n");
check(s1, s2, compvalues);
}
else
{
printf("Testing strings for equality.\n");
check(s1, s2, strcmp);
}
return 0;
}
void check(char *a, char *b,
int (*cmp) (const char *, const char *))
{
if (!(*cmp)(a,b)) printf("Equal");
else printf("Not Equal");
}
int compvalues(const char *a, const char *b)
{
if (atoi(a) ==atoi(b)) return 0;
else return 1;
}