最佳實踐
使用 typedef
使用 typedef
而不是每次手動宣告函式指標可能很方便。
宣告函式指標的 typedef
的語法是:
typedef returnType (*name)(parameters);
例:
假設我們有一個函式 sort
,它需要一個函式指向函式 compare
,這樣:
compare - 要提供給 sort 函式的兩個元素的比較函式。
如果兩個元素被認為相等,則
compare
預期返回 0,如果傳遞的第一個元素在某種意義上比後一個元素更大則返回正值,否則函式返回負值(意味著第一個元素是比後者更小。
如果沒有 typedef
,我們會以下列方式將函式指標作為引數傳遞給函式:
void sort(int (*compare)(const void *elem1, const void *elem2)) {
/* inside of this block, the function is named "compare" */
}
有了 typedef
,我們寫道:
typedef int (*compare_func)(const void *, const void *);
然後我們可以將 sort
的函式簽名更改為:
void sort(compare_func func) {
/* In this block the function is named "func" */
}
sort
的兩個定義都接受該形式的任何功能
int compare(const void *arg1, const void *arg2) {
/* Note that the variable names do not have to be "elem1" and "elem2" */
}
函式指標是唯一應該包含該型別的指標屬性的地方,例如,不要嘗試定義像 typedef struct something_struct *something_type
這樣的型別。這甚至適用於具有不應由 API 呼叫者直接訪問的成員的結構,例如 stdio.h FILE
型別(你現在將注意到它不是指標)。
採用上下文指標
函式指標幾乎總是將使用者提供的 void *作為上下文指標。
例
/* function minimiser, details unimportant */
double findminimum( double (*fptr)(double x, double y, void *ctx), void *ctx)
{
...
/* repeatedly make calls like this */
temp = (*fptr)(testx, testy, ctx);
}
/* the function we are minimising, sums two cubics */
double *cubics(double x, double y, void *ctx)
{
double *coeffsx = ctx;
double *coeffsy = coeffx + 4;
return coeffsx[0] * x * x * x + coeffsx[1] * x * x + coeffsx[2] * x + coeffsx[3] +
coeffsy[0] * y * y * y + coeffsy[1] * y * y + coeffsy[2] * y + coeffsy[3];
}
void caller()
{
/* context, the coefficients of the cubics */
double coeffs[8] = {1, 2, 3, 4, 5, 6, 7, 8};
double min;
min = findminimum(cubics, coeffs);
}
使用上下文指標意味著額外的引數不需要硬編碼到指向的函式中,或者需要使用全域性變數。
庫函式 qsort()
不遵循這個規則,並且人們經常可以在沒有上下文的情況下來避免瑣碎的比較函式。但對於任何更復雜的事情,上下文指標變得至關重要。