函数指针和指针函数的区别与使用(C语言小白也能看懂) 很多同学第一次看到下面两行代码会懵:

C
int (*fp)(int, int);
int *func(int, int);

它们看起来很像,但含义完全不同。本文带你一次讲透。

一、先记住核心区别

函数指针:本质是指针,这个指针指向一个函数。 指针函数:本质是函数,这个函数的返回值是一个指针。

一句话口诀:

`(*xxx)` 大概率是“xxx 是指针”(函数指针)

`xxx(...)` 大概率是“xxx 是函数”(指针函数)

二、函数指针:指向函数的指针

1)声明形式

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

示例:

C
#include <stdio.h>

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

int main() {
    int (*fp)(int, int); // 函数指针
    fp = add;            // 或 fp = &add
    printf("%d\n", fp(2, 3)); // 5
    return 0;
}

2)常见用途

回调函数(最常见) 函数分发(函数表) 策略切换(不同算法动态替换)

3)回调示例

C
#include <stdio.h>

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

int calc(int x, int y, int (*op)(int, int)) {
    return op(x, y);
}

int main() {
    printf("add: %d\n", calc(10, 3, add)); // 13
    printf("sub: %d\n", calc(10, 3, sub)); // 7
    return 0;
}

三、指针函数:返回指针的函数

1)声明形式

C
返回类型* 函数名(参数列表);

示例:

C
#include <stdio.h>

int* getMaxPtr(int *a, int *b) { // 指针函数
    return (*a > *b) ? a : b;
}

int main() {
    int x = 10, y = 20;
    int *p = getMaxPtr(&x, &y);
    printf("max = %d\n", *p); // 20
    return 0;
}

2)常见用途

返回数组或缓冲区地址 返回结构体/链表节点指针 在数据结构中返回“找到的目标地址”

四、最容易混淆的写法对比

C
int (*fp)(int, int); // 函数指针:fp 是指针
int *func(int, int); // 指针函数:func 是函数,返回 int*

关键是看变量名和谁先结合:

`fp` 被 `(*fp)` 包起来,说明它是指针;

`func` 后面直接是 `()`,说明它是函数。

五、推荐写法:typedef 提高可读性

函数指针原写法不好读,建议使用 `typedef`:

C
#include <stdio.h>

typedef int (*OpFunc)(int, int);

int mul(int a, int b) { return a * b; }
int divi(int a, int b) { return b == 0 ? 0 : a / b; }

int apply(int x, int y, OpFunc f) {
    return f(x, y);
}

int main() {
    printf("mul: %d\n", apply(12, 3, mul));  // 36
    printf("div: %d\n", apply(12, 3, divi)); // 4
    return 0;
}

六、实战:函数指针数组做“迷你计算器”

C
#include <stdio.h>

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int divi(int a, int b) { return b == 0 ? 0 : a / b; }

int main() {
    int (*ops[4])(int, int) = {add, sub, mul, divi};
    const char *names[4] = {"add", "sub", "mul", "div"};

    int x = 20, y = 5;
    for (int i = 0; i < 4; i++) {
        printf("%s(%d, %d) = %d\n", names[i], x, y, ops[i](x, y));
    }
    return 0;
}

七、常见坑(面试和考试都爱问)

1)返回局部变量地址(危险)

C
int* wrong() {
    int x = 10;
    return &x; // 错误:x 是局部变量,函数结束后地址失效
}

2)函数指针类型不匹配

C
int f(int a);
double (*p)(int); // 不能指向 f,返回类型不一致

3)少了括号语义就变了

C
int *fp(int, int);   // 指针函数
int (*fp)(int, int); // 函数指针

八、总结

函数指针:指向函数,用来“把函数当参数传来传去”。 指针函数:返回地址,用来“把某块内存/对象地址返回给调用方”。 记忆重点:`()` 优先级高于 `*`,必要时用括号明确含义。 工程建议:函数指针优先搭配 `typedef`,代码更清晰、更易维护。

如果你是新手,建议先把文中的 4 个示例都自己敲一遍,再改参数和返回值做实验,理解会非常扎实。