| 概念 | 本質 | 聲明語法 | 核心用途 |
|---|---|---|---|
| 指針函數 | 函數,返回指針 | type *func(args) | 返回動態內存、靜態數組元素地址、鏈表節點 |
| 函數指針 | 指針,指向函數 | type (*funcPtr)(args) | 回調、多態、狀態機、插件架構、qsort 比較器 |
記憶口訣:「指針函數」中心詞是「函數;「函數指針」中心詞是「指針。
int *getPtr(); // 返回 int*
Node *createNode(); // 返回結構體指針
int (*getRow(int))[4]; // 返回指向 int[4] 的指針
int calendar[5][7] = { /* ... */ };
// 返回指定周、日的元素地址
int *getDate(int week, int day) {
if (week < 1 || week > 5 || day < 1 || day > 7) return NULL;
return &calendar[week-1][day-1];
}
int main() {
int w, d;
scanf("%d%d", &w, &d);
int *p = getDate(w, d);
if (p) printf("Value: %d\n", *p);
else puts("Invalid input");
return 0;
}
NULL 表示失敗/無效。// 基本聲明
void (*funcPtr)(int, int); // 指向 void(int,int) 的指針
// typedef 簡化
typedef int (*CmpFunc)(const void*, const void*);
CmpFunc cmp = myCompare;
// 賦值:函數名隱式轉換為地址
void foo(int a) { printf("%d\n", a); }
void (*p)(int) = foo; // &foo 同義
p(42); // 調用:(*p)(42) 或 p(42)
// 通用處理函數
void process(int *arr, int n, void (*op)(int*)) {
for (int i = 0; i < n; i++) op(&arr[i]);
}
// 具體操作
void doubleVal(int *x) { *x *= 2; }
void squareVal(int *x) { *x *= *x; }
int main() {
int a[] = {1,2,3,4,5};
process(a, 5, doubleVal); // 2 4 6 8 10
process(a, 5, squareVal); // 4 16 36 64 100
return 0;
}
int cmpInt(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int arr[] = {5,2,8,1,9};
qsort(arr, 5, sizeof(int), cmpInt); // 1 2 5 8 9
當函數需要修改調用者的指針變量(如分配內存、鏈表頭插入),需傳遞指針的地址。
void allocate(int **ptr, int n) {
*ptr = malloc(n * sizeof(int)); // 修改調用者的指針
}
int main() {
int *p = NULL;
allocate(&p, 10); // 傳遞 p 的地址
// p 現在指向有效內存
free(p);
return 0;
}
char c = 'A';
char *p1 = &c; // 一級指針
char **p2 = &p1; // 二級指針
char ***p3 = &p2; // 三級指針 (罕見)
*p2 == p1; // 取得一級指針
**p2 == c; // 取得最終數據
char *names[] = {"Alice", "Bob", "Charlie", NULL};
char **p = names;
while (*p) {
printf("%s\n", *p++); // *p 取得字符串指針,p++ 移動到下一個
}
優勢:動態增減字符串,無需移動數據,僅調整指針數組。NULL 終結符簡化遍歷。
typedef double (*OpFunc)(double, double);
double add(double a, double b) { return a + b; }
double sub(double a, double b) { return a - b; }
double mul(double a, double b) { return a * b; }
double div(double a, double b) { return b ? a/b : 0; }
OpFunc ops[] = {add, sub, mul, div};
char *syms[] = {"+", "-", "*", "/"};
int main() {
double x, y; char op;
scanf("%lf %c %lf", &x, &op, &y);
for (int i = 0; i < 4; i++) {
if (op == syms[i][0]) {
printf("%.2f\n", ops[i](x, y));
break;
}
}
return 0;
}
typedef 提升可讀性。NULL 終結的指針數組處理變長字符串列表。