【问题标题】:Defining and calling higher-order function composition functions with function pointers in C在 C 中使用函数指针定义和调用高阶函数组合函数
【发布时间】:2019-11-27 09:53:44
【问题描述】:

function types 上的维基百科文章列出了一个有趣的“高阶函数组合函数”声明:

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 function function-pointers function-composition


    【解决方案1】:

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

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

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

    #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

    (*) - 从理论上讲,您可以执行运行时编译并返回指向结果机器代码地址的链接,但这不是语言工具。在实践中这无关紧要

    【讨论】:

    • 您更改了函数签名,简化了问题。我想按照给定的方式实现 Wiki 声明。
    • 虽然我不能接受这个答案,因为签名改变了,我喜欢这个简单的解决方案——谢谢!
    【解决方案2】:

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

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

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

    int r = (*compose(&a, &b))(x);
    

    那么你需要让compose返回一个指向函数的指针,其中包括创建要返回的函数:

    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_) { ... }
    

    【讨论】:

    • 感谢您指出错误所在,但您还没有提出可行的解决方案,我至今无法创建它。请考虑编辑您的答案,以便在作文中使用我的 a 和 b 函数。
    • @Theod'Or 但是ab 使用了...它们存储在全局变量f1f2 中,它们被称为compose_helper.
    • 当然!答案被接受,因为它展示了如何实现 Wiki 声明。
    【解决方案3】:

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

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-21
      • 2010-11-26
      • 1970-01-01
      • 2021-06-27
      相关资源
      最近更新 更多