最佳实践
使用 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()
不遵循这个规则,并且人们经常可以在没有上下文的情况下来避免琐碎的比较函数。但对于任何更复杂的事情,上下文指针变得至关重要。