標準庫 qsort 要求比較函數簽名為:
int (*compar)(const void*, const void*);
但我們常寫類型安全的比較函數,如 int cmp(double*, double*),調用時需強制轉換。
// 顯式指定返回類型、調用約定、參數類型 (int (__cdecl *)(const void*, const void*)) cmpb
int — 返回類型__cdecl — 調用約定(Windows 默認)(const void*, const void*) — 參數列表cmpb — 被轉換的函數名(隱式轉為函數指針)#include <cstdlib>
#include <iostream>
using namespace std;
// 標準簽名版本
int cmpa(const void* a, const void* b) {
double da = *static_cast(a);
double db = *static_cast(b);
return (da > db) - (da < db);
}
// 類型安全版本(需轉換調用)
int cmpb(const double* a, const double* b) {
return (*a > *b) - (*a < *b);
}
int main() {
double arr[] = {1, 3, 4, 2, 5};
const int n = 5;
// 直接用標準簽名
qsort(arr, n, sizeof(double), cmpa);
// 強制轉換類型安全版本
qsort(arr, n, sizeof(double),
(int (__cdecl *)(const void*, const void*))cmpb);
for (double v : arr) cout << v << ' ';
return 0;
}
| 概念 | 定義 | 本質 | 示例 |
|---|---|---|---|
| 函數指針 | 指向函數的指針 | 指針 | int (*pf)(int, int); |
| 指針函數 | 返回指針的函數 | 函數 | int* func(int, int); |
// 返回指向 float 陣列的指針(一維數組指針)
float* find(float (*p)[4], int m) {
return *(p + m); // p 指向包含 4 個 float 的數組,p+m 跳過 m 個學生
}
int main() {
float score[][4] = {{50,51,52,55}, {70,70,40,80}, {77,99,88,67}};
int m; cin >> m;
float* pf = find(score, m);
for (int i = 0; i < 4; ++i) cout << pf[i] << ' ';
return 0;
}
「函數指針」:指針是主語,指向函數。
「指針函數」:函數是主語,返回指針。
宣告時看 * 最近綁定誰:int (*pf)() 中 * 綁定 pf → 指針;int *pf() 中 * 綁定返回類型 → 函數。
函數指針強制轉換是 C/C++ 互操作舊式 API(如 qsort、Windows 回調)的常用技巧,語法雖顯晦澀但遵循固定模式。理解「函數指針」與「指針函數」的區別有助於閱讀複雜聲明,避免誤用。