在 C 中使用函数指针定义和调用高阶函数组合函数

Defining and calling higher-order function composition functions with function pointers in C

function types 上的维基百科文章列出了 "higher-order function composition function" 的有趣声明:

int (*compose(int (*f)(int), int (*g)(int)))(int);

作为学习练习,我想在测试程序中实现它,但失败了,编译器抛出了一些警告和错误。我的尝试:

int a(int x) {
    return x + 1;
}

int b(int x) {
    return x * 2;
}

int (*compose(int (*f)(int y), int (*g)(int z)))(int x) {
    return (*f)(x) - (*g)(x);
}

int main(void) {
    int x = 5;
    int r = (*compose)((*a)(x), (*b)(x))(x);
    printf("Compose result for x = %d: %d\n", x, r);

    return 0;
}

如果您能解释维基百科的声明与 f(g(h(x))) 等简单函数组合的不同之处,以及如何实现它,最好是使用类似于我的简单程序,我将不胜感激。

这里有几个问题需要解决。

  • 在 C 中,您不能在 运行 时动态组合函数;仅在编译时静态地。因此,您无法使用为 compose 选择的签名实现您所追求的 运行 时间合成。如果 compose 是 return 一个(指向一个)函数的指针 - 它只能 return 一个预先存在的函数。 (*)
  • 在 C 语言中,当您使用一个函数的标识符(您已经定义过)时 - 该类型实际上已经是一个函数指针,即 "invocation operator"(或 "parentheses operator")始终适用于函数指针。
  • 你的语法有点不对。

尝试对您的代码进行此修改:

#include <stdio.h> 

int a(int x) {
    return x + 1;
}

int b(int x) {
    return x * 2;
}

int compose(int (*f)(int y), int (*g)(int z), int x) {
    return f(x) - g(x);
}

int main(void) {
    int x = 5;
    int r = compose(a, b, x);
    printf("Compose result for x = %d: %d\n", x, r);

    return 0;
}

这个compiles.

(*) - 理论上您可以执行 运行-time 编译和 return a link 到生成的机器代码的地址,但事实并非如此语言设施。实际上这无关紧要

您的 compose 函数被声明为 return 一个函数指针,但计算 return 一个 int 值。

(*a)(x) 调用 a 函数,您将 int 结果传递给 compose,而不是指向函数 a 本身的指针。与 b.

相同

要解决您的问题,您首先应该使用指向函数 ab:

的指针调用 compose
int r = (*compose(&a, &b))(x);

然后你需要让 compose return 成为一个指向函数的指针,其中包括创建要被 returned:

的函数
int (*f1)(int);
int (*f2)(int);

int compose_helper(int x)
{
    return f1(x) - f2(x);
}

int (*compose(int (*f1_)(int), int (*f2_)(int)))(int)
{
    f1 = f1_;
    f2 = f2_;
    return &compose_helper;
}

在 C 中确实没有很好的方法来做到这一点,因为函数组合不能在 运行 时间完成并且需要全局状态。


作为旁注,我真的建议您为函数指针创建类型别名,以使其更易于阅读和理解。

typedef int (fp_type)(int);

fp_type *f1;
fp_type *f2;

fp_type *compose(fp_type *f1_, fp_type *f2_) { ... }

在 C 中,您不能在运行时创建新函数; compose 只能return 一个预定义函数。这是此类函数的简短示例:

int null(int x) { return 0; }
int f1(int x) { return x*x; }
int f2(int x) { return 2*x; }

int sub_f2_f1 ( int x ) { return f2(x)-f1(x); }
int sub_f1_f2 ( int x ) { return f1(x)-f2(x); }
/*...*/

int (*compose(int (*f)(int), int (*g)(int)))(int)
{
  if (f1==f2) return null;
  if (f2==null) return f1;
  if (f==f2 && g==f1) return sub_f2_f1;
  if (f==f1 && g==f2) return sub_f1_f2;
  /*...*/
  return 0;
}