在 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
.
相同
要解决您的问题,您首先应该使用指向函数 a
和 b
:
的指针调用 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;
}
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
.
要解决您的问题,您首先应该使用指向函数 a
和 b
:
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;
}