一、指向函數的指針
1. 函數指針本質
- 函數編譯後在代碼區有入口地址,函數名即首地址(類似數組名)。
- 將首地址賦給指針變量,即可通過指針調用函數。
2. 三步驟
- 聲明:
返回類型 (*指針名)(參數列表); 如 int (*pfun)(int, int);
- 賦值:
pfun = func_name; (或 &func_name)
- 調用:
(*pfun)(args); 或 pfun(args); (C99 允許隱式解引用)
3. 完整示例:求最大值
#include <stdio.h>
int max(int *p) {
int i, t = *p;
for (i = 1; i < 10; ++i)
if (*(p+i) > t) t = *(p+i);
return t;
}
int main() {
int a[10], i, m;
int (*f)();
for (i = 0; i < 10; ++i) scanf("%d", &a[i]);
f = max;
m = (*f)(a);
printf("max=%d\n", m);
return 0;
}
4. 函數指針作參數(回調/策略模式)
void process(int x, int y, int (*fun)(int, int)) {
int result = (*fun)(x, y);
printf("%d\n", result);
}
int add(int a, int b) { return a+b; }
int max(int a, int b) { return a>b?a:b; }
int min(int a, int b) { return a<b?a:b; }
int main() {
int a, b; scanf("%d%d", &a, &b);
process(a, b, min);
process(a, b, max);
process(a, b, add);
}
二、返回指針的函數
1. 聲明語法
返回類型 *函數名(參數列表);
2. 關鍵規則
- **不能返回局部變量地址**(棧內存函數返回即失效)。
- 可返回:靜態局部變量地址、全局變量地址、動態分配內存地址(調用者負責釋放)、傳入參數的地址。
3. 示例:返回兩數中較大者的地址
int *fun(int x, int y) {
static int z;
if (x > y) z = x; else z = y;
return &z;
}
int main() {
int *p, i, j;
scanf("%d%d", &i, &j);
p = fun(i, j);
printf("max=%d\n", *p);
}
三、易混淆點辨析
| 聲明 | 含義 | 例子 |
int *fun(); | 返回 int* 的函數 | 函數指針 |
int (*fun)(); | 指向函數的指針 | 函數指針變量 |
int (*fun[])(); | 函數指針數組 | 狀態機/命令表 |
int (*(*fun)[])(); | 指向函數指針數組的指針 | 極少用 |
四、現代 C++ 替代方案
std::function<Ret(Args...)>:類型擦除,可存儲函數、Lambda、仿函數。
- Lambda 表達式:
auto f = [](int a, int b){ return a+b; };
- 模板傳遞可調用對象:
template<typename F> void process(F f); 零開銷、類型安全。