最佳实践

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

也可以看看

函数指针