在C语言中指针函数和函数指针是两个极易混淆的概念。它们的名字只是词序不同但含义截然相反。下面我将从定义、用法、典型场景到复杂声明为你彻底厘清这两个概念。一、指针函数 —— 返回指针的函数1. 概念指针函数本质上是一个函数它的返回值类型是一个指针也就是一个地址。2. 定义格式int *func(int a, int b); // func 是函数返回 int* 类型的指针解读func先和(int a, int b)结合说明它是一个函数函数的返回值是int *类型。3. 典型例子返回一个静态变量的地址char *get_weekday(int n) { static char *weekdays[] { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }; if (n 1 || n 7) return NULL; return weekdays[n - 1]; } char *day get_weekday(3); // day 指向 Wednesday注意这里使用了static修饰数组因为如果返回局部非静态数组的地址函数退出后该内存会被回收返回的指针就是“野指针”。返回动态分配的内存int *create_array(int size) { int *p (int *)malloc(size * sizeof(int)); return p; // 返回堆内存的指针 }这是合法的因为堆内存的生命周期由程序员手动控制。但调用方必须记得free。4. 注意事项绝不能返回局部非静态变量的地址。返回的指针在使用前需检查是否为空如malloc失败。返回指针的函数常用于分配资源、查找子串、返回结构体指针等场景。二、函数指针 —— 指向函数的指针1. 概念函数指针是一个指针变量它存储的是函数的入口地址。通过它可以间接调用函数如同通过数据指针间接访问变量一样。2. 定义格式int (*p)(int, int); // p 是指针指向 返回值为int、参数为(int, int) 的函数解读因为括号的优先级*p先结合表明p是一个指针然后外面是函数的调用操作符(int, int)表明它指向一个函数函数返回int。若不写括号int *p(int, int)则声明的是一个指针函数返回int*的函数所以括号非常关键。3. 初始化与调用int add(int a, int b) { return a b; } int sub(int a, int b) { return a - b; } int (*pfunc)(int, int) add; // 初始化取地址符可以省略等价于 add int result pfunc(3, 4); // 通过指针调用等价于 (*pfunc)(3, 4)4. 主要用途(1) 回调函数将函数作为参数传给另一个函数实现灵活的定制行为。标准库的qsort就是典型例子#include stdlib.h int cmp_int(const void *a, const void *b) { return (*(int *)a - *(int *)b); } int arr[] {5, 2, 8, 1, 9}; qsort(arr, 5, sizeof(int), cmp_int); // cmp_int 就是一个函数指针实参(2) 函数指针数组将一系列函数按序号放入数组实现类似“跳转表”的功能常用于菜单驱动、有限状态机等。void func0() { printf(Menu 0\n); } void func1() { printf(Menu 1\n); } void func2() { printf(Menu 2\n); } void (*menu[])(void) {func0, func1, func2}; int choice 1; if (choice 0 choice 3) menu[choice](); // 调用 func1(3) 结构体中的函数指针可在结构体中封装“行为”模拟简易的面向对象。struct Calculator { int (*op)(int, int); }; int multiply(int a, int b) { return a * b; } struct Calculator calc; calc.op multiply; int product calc.op(6, 7); // 425. 复杂声明与typedef简化函数指针的声明如果嵌套多层会非常难读例如void (*(*pf)(int, void (*)(int)))(int);这种时候强烈推荐用typedef分步定义typedef void (*Callback)(int); // 函数指针类型参数int返回void typedef Callback (*ComplexFunc)(int, Callback); // 返回 Callback 的函数指针 ComplexFunc pf; // 这样清晰多了三、核心区别对比项目指针函数函数指针本质函数返回值为指针变量存储函数地址声明示例int *f(int);int (*f)(int);用法调用后得到一个地址通过它调用所指的函数常见场景动态内存分配、返回字符串数组回调、策略模式、跳转表内存占用函数体代码 返回值指针只占一个指针大小的内存4/8 字节语法中的括号不需要额外括号必须用括号将*和指针名括起来四、一张 Mermaid 脑图帮你记住五、小结指针函数的核心是“函数”它返回一个地址函数指针的核心是“指针”它指向一个函数。书写时牢记括号的优先级int (*p)()表示p是指针int *p()表示p是函数返回指针。熟练掌握函数指针是理解回调机制、编写灵活库和阅读Linux内核源码等进阶内容的基础。