1.在C语言中,函数名也是指针变量,创建一个a()函数的同时也会创建一个叫a的指针变量,变量中保存了函数的地址。
2.函数指针: 返回类型(*指针变量)(参数类型)
int (*match)(char*)
3.void指针可以保存任何类型的指针
4.函数指针数组:
返回类型(*指针变量)(参数类型)
例如:enum response_type{DUMP,SECOND_CHANCE,MARRIAGE};
写成:viod(*replies[])(response) = {dump,second_chance,marriage};
*注意:在数组中,函数名的顺序与枚举类型的顺序完全相同,因为当c语言在创建枚举时会给每个符号分配一个从0开始的数字,所以DUMP == 0;也就是说可以用respond_type获取数组中的函数指针。
replies[SECOND_CHANCE] == second_chance
举例
int main() { response r[] = { {"Mike",DUMP},{"Luis",SECOND_CHANCE}, {"Matt",SECOND_CHANCE},{"William",MARRIAGE} }; int i; for(i = 0;i < 4;i++) { switch(r[i].type) { case DUMP: dump(r[i]); break; case SECOND_CHANCE: second_chance(r[i]); break; default: marriage(r[i]); } } return 0; }
可以改写成(便于增加新的回复类型,使代码易于伸缩)
void (*replies[])(response) = {dump,second_chance,marriage}; int main() { response r[] = { {"Mike",DUMP},{"Luis",SECOND_CHANCE}, {"Matt",SECOND_CHANCE},{"William",MARRIAGE} }; int i; for(i = 0;i < 4;i++) { (*replies[r[i].type])(r[i]);//*replies[r[i].type]是所指向的那个函数 } return 0; }
5.函数指针是唯一不需要加*和&运算符的指针(也可以加上)
练习使用函数指针
#include<stdio.h> #include<stdlib.h> int NUM_ADS = 7; char *ADS[] = { "William:SBM GSOH likes sports,TV,dining.", "Matt:SWM NS likes art,movies,theater.", "Luis:SLM ND likes book,theater,art.", "Mike:DWM DS likes trucks,sports and bieber.", "Peter:SAM likes chess,working out and art.", "Josh:SJM likes sports,movies and theater.", "Jed:DBM likes theater,books and dining." }; int sports_no_bieber(char *s) { return strstr(s,"sports") && !strstr(s,"bieber"); } int sports_or_workout(char *s) { return strstr(s,"sports") || strstr(s,"working out"); } int ns_theater(char *s) { return strstr(s,"NS") && strstr(s,"theater"); } int arts_theater_or_dining(char *s) { return strstr(s,"arts") || strstr(s,"theater") || strstr(s,"dining"); } void find(int (*match)(char*))//名为match的指针,指向一个函数 { int i; puts("Search results:"); puts("----------------------------"); for (i = 0;i < NUM_ADS;i++) { if(match(ADS[i])) //可以写成(*match)(ADS[i]) printf("%s ",ADS[i]); } puts("----------------------------"); } int main() { find(sports_no_bieber); //可以写成find(&sports_no_bieber); find(sports_or_workout); find(ns_theater); find(arts_theater_or_dining); return 0; }
练习二
#include<stdio.h> #include<stdlib.h> #include<string.h> qsort(void *array, size_t length, size_t item_size, int (*compar)(const void *,const void *)); //升序排列整数 int compare_scores(const void * score_a,const void * score_b) { int a = *(int*)score_a;//把void型指针转化为int型指针 int b = *(int*)score_b; return a - b; } //降序排列整型得分 int compare_scores_desc(const void * score_a,const void * score_b) { int a = *(int*)score_a; int b = *(int*)score_b; return b - a; } //按面积从小到大排列矩形 typedef struct { int width; int height; }rectangle; int compare_areas(const void *a,const void *b) { rectangle *ra = (rectangle*)a; rectangle *rb = (rectangle*)b; int area_a = ra->width * ra->height; int area_b = rb->width * rb->height; return area_a - area_b; } //按字母排列名字,区分大小写 int compare_name(const void *a,const void *b) { char** ra = (char**)a; char** rb = (char**)b;//字符串是字符指针,所以得到的是指针的指针 return strcmp(*ra,*rb); } //按面积从大到小排列矩形 int compare_areas_desc(const void *a,const void *b) { return compare_areas(b,a);//可以写成 -compare_areas(a,b) } //按逆字母排列名字,区分大小写 int compare_name_desc(const void *a,const void *b) { return compare_names(b,a);//可以写成 -compare_names(a,b) } int main() { int scores[] = {543,323,32,554,11,3,112}; int i; qsort(scores,7,sizeof(int),comepare_scores_desc); puts("These are the scores in order:"); for(i = 0;i < 7;i++) printf("Score = %i ",scores[i]); char *names[] = {"Karen","Mark","Brett","Molly"}; qsort(names,4,sizeof(char*),compare_names); puts("These are the names in order:"); for(i = 0;i < 4;i++) printf("%s ",names[i]); return 0; }
练习三
#include <stdio.h> enum response_type{DUMP,SECOND_CHANCE,MARRIAGE}; typedef struct { char *name; enum reponse_type type; }response; void dump(response r) { printf("Dear %s, ",r.name); puts("Unfortunately your last date contacted us to"); puts("say that they will not be seeing you again"); } void second_chance(response r) { printf("Dear %s, ",r.name); puts("Good news: your last date has asked us to"); puts("arrange another meeting. Please call ASAP"); } void marriage(response r) { printf("Dear %s, ",r.name); puts("Congratulations! Your last date has contacted"); puts("us with a proposal of marriage."); } int main() { response r[] = { {"Mike",DUMP},{"Luis",SECOND_CHANCE}, {"Matt",SECOND_CHANCE},{"William",MARRIAGE} }; int i; for(i = 0;i < 4;i++) { switch(r[i].type) { case DUMP: dump(r[i]); break; case SECOND_CHANCE: second_chance(r[i]); break; default: marriage(r[i]); } } return 0; }