在C语言中,函数存放在内存的代码区,跟基本的数据类型或者数组一样,也有一个内存的起始位置。函数的类型由其参数以及返回类型共同决定,跟函数名无关。
一个简单的例子
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
int (*pf)(int, int);
pf = add;
printf(" pf(1, 2) = %d\n", pf(1, 2));
printf("(*pf)(1, 2) = %d\n", (*pf)(1, 2));
}
// 编译执行可以正常输出:
// cc demo1.c -o demo1
// demo1
// pf(1, 2) = 3
// (*pf)(1, 2) = 3
函数指针定义
直接定义
返回数据类型 (*函数指针名称) (入参类型列表逗号分隔)
例子
int (*pf)(int, int);
使用typedef定义
typedef 返回数据类型 (*函数指针类型名称) (入参类型列表逗号分隔)
例子
type int (*PF)(int, int);
PF pf;
此时PF
是指针函数类型,不是真正的函数指针变量,需要使用该类型定义出函数指针变量使用。
函数指针的使用
作为变量
如同开头简单的例子所示,函数指针变量作为普通变量几乎没什么意义,还不如直接调用函数。放到结构体中,是不是有点像C++或者Java面向对象的味道了?
#include <stdio.h>
struct Student {
unsigned int id;
char *name;
void (*print)(struct Student *stu);
};
void PrintInfo(struct Student *stu) {
printf("%d -- %s\n", stu->id, stu->name);
}
int main() {
struct Student stu = {1, "raveh", PrintInfo};
stu.print(&stu);
}
// 编译执行可以正常输出:
// cc demo2.c -o demo2
// demo2
// 1 -- raveh
作为函数形参
一个例子,可以让数据给不同的函数去处理:
#include <stdio.h>
#include <stdlib.h>
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a > b ? b : a;
}
void proc(int a, int b, int(*pf)(int, int)) {
printf("a=%d, b=%d, pf(%d,%d)=%d\n", a, b, a, b, pf(a, b));
}
int main() {
int a = rand(), b = rand();
proc(a, b, max);
proc(a, b, min);
}
// 编译执行可以正常输出:
// cc demo3.c -o demo3
// demo3
// a=1804289383, b=846930886, pf(1804289383,846930886)=1804289383
// a=1804289383, b=846930886, pf(1804289383,846930886)=846930886
这个程序可以使用typedef定义一个函数指针,使proc函数的参数列表看起来更清晰一点。
#include <stdio.h>
#include <stdlib.h>
typedef int(*PF)(int, int);
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a > b ? b : a;
}
void proc(int a, int b, PF pf) {
printf("a=%d, b=%d, pf(%d,%d)=%d\n", a, b, a, b, pf(a, b));
}
int main() {
int a = rand(), b = rand();
proc(a, b, max);
proc(a, b, min);
}
// 编译执行可以正常输出:
// cc demo4.c -o demo4
// demo4
// a=1804289383, b=846930886, pf(1804289383,846930886)=1804289383
// a=1804289383, b=846930886, pf(1804289383,846930886)=846930886
作为函数返回值
#include <stdio.h>
#include <stdlib.h>
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a > b ? b : a;
}
/**
* 可以按照由内向外的顺序看这个函数的声明
* getFun(char oper)有形参列表,则getFun是一个函数
* getFun前面有*,所以getFun返回一个指针
* 返回的指针本身也包含形参列表(int,int)
* 因此返回的指针指向一个返回值为int的函数
*/
int (*getFun(char oper))(int, int) {
switch(oper) {
case '>':
return max;
break;
case '<':
return min;
break;
}
return NULL;
}
int proc(int a, int b, char oper) {
int(*pf)(int,int) = getFun(oper);
if(pf) {
return pf(a, b);
}
return -1;
}
int main() {
int a = rand(), b = rand();
printf("proc(%d, %d, %c) = %d\n", a, b, '>', proc(a, b, '>'));
printf("proc(%d, %d, %c) = %d\n", a, b, '<', proc(a, b, '<'));
}
// 编译执行可以正常输出:
// cc demo5.c -o demo5
// demo5
// proc(1804289383, 846930886, >) = 1804289383
// proc(1804289383, 846930886, <) = 846930886