蔚淦丞
发布于 2026-09-27 / 19 阅读
0
0

函数指针

一、什么是函数指针?

普通指针保存的是:数据的地址。函数指针保存的是:函数入口地址

例如:

void hello()
{
    printf("hello\n");
}

函数名 hello 本身就是函数地址。

可以:

void (*p)();

p = hello;

p();

二、函数指针定义方式

语法:

返回值类型 (*指针名)(参数列表);

例如:

普通函数:

int add(int a, int b)
{
    return a+b;
}

函数指针:

int (*p)(int,int);

含义:

p指向:

  • 返回int

  • 参数两个int

的函数。

p = add;
int result = p(1,2);
int result2 = add(1,2); // 二者等价

三、为什么需要函数指针?

核心:

实现运行时选择函数。

比如:

普通写法:

if(type == 1)
{
    add();
}
else if(type == 2)
{
    sub();
}

如果有100种操作:

代码很难维护。

函数指针:

建立一个函数表:

func_table[type]();

四、最常见场景:回调函数

例如,有一个排序函数:

void sort(int *arr, int n, int (*cmp)(int,int))
{
}

cmp就是函数指针。

升序:

int ascending(int a,int b)
{
    return a>b;
}

降序:

int descending(int a,int b)
{
    return a<b;
}

调用:

sort(arr,n,ascending);

sort内部:

if(cmp(a,b))
{
    swap();
}

这样排序逻辑可以和比较规则解耦。


五、工程里面的典型用途

1. 状态机

比如服务端响应协议:

请求类型:

#define LOGIN_REQ 1
#define QUERY_REQ 2
#define DOWNLOAD_REQ 3

如果不用函数指针:

switch(type)
{
case LOGIN_REQ:
    login_handler();
    break;

case QUERY_REQ:
    query_handler();
    break;
}

函数越来越多,switch越来越大。

使用函数指针可以:

typedef void (*handler)(void);


handler table[3]=
{
    login_handler,
    query_handler,
    download_handler
};

收到请求:

table[type]();

这就是网络服务器常见设计。


2. 面向对象抽象

定义接口:

struct device_ops
{
    int (*open)();
    int (*close)();
    int (*send)(char *);
};

不同厂商:

broadcom_ops
marvell_ops

实现不同函数。

上层调用:

ops->send(data);

不用关心底层是谁。


六、typedef简化函数指针

原始:

int (*callback)(int,int);

typedef:

typedef int (*callback)(int,int);

以后:

callback cb;

等价:

int (*cb)(int,int);

七、函数指针和普通指针区别

面试回答:

普通指针

函数指针

保存

数据地址

函数地址

用途

访问变量

调用函数

例子

int *p

int (*p)(int)


八、几个容易错的地方

1. 括号不能少

错误:

int *func();

表示:

一个返回int*的函数

不是函数指针。

正确:

int (*func)();

表示:

一个指向函数的指针


2. 函数名和&函数名等价

例如:

p = add;

等价:

p = &add;


评论