Gre*_*con 18
作为对你的问题的评论,Basile Starynkevitch建议阅读关于闭包的内容.从本质上讲,一个闭包结合了一个被调用的函数和一些上下文,在文献中称为函数的环境.
面向对象的语言具有类似的概念,称为委托,其中特定实例可以成为稍后调用的环境,其中调用站点不直接了解底层对象.支持闭包的语言本身自动捕获或"关闭"环境中提供的绑定.这似乎是一种奇怪的语言特征,但它可以表达和有用,因为你的问题背后的动机暗示.
下面是在C程序中工作的闭包概念的一个简单示例,由程序员明确指示捕获.
你想最终调用的函数加上一些前面的事情是
#include <stdio.h>
int
add_two_numbers(int a, int b)
{
return a+b;
}
Run Code Online (Sandbox Code Playgroud)
闭包是一种与其环境相结合的函数.在C中,要调用的函数是指向函数的指针.注意f与那些参数对齐的参数add_two_numbers.
typedef struct {
struct { /* environment */
int a;
int b;
} env;
int (*f)(int, int); /* function to be called */
} closure;
Run Code Online (Sandbox Code Playgroud)
我们想创建一个闭包,即设置参数值的关联,以便在我们准备好时调用要调用的函数.在这个简单的例子中,make_adder留下了为其调用者分配闭包空间的问题.
void
make_adder(int a, int b, closure *c)
{
c->env.a = a;
c->env.b = b;
c->f = add_two_numbers;
}
Run Code Online (Sandbox Code Playgroud)
既然您知道如何创建我们的简单闭包之一,那么您可以调用或调用它
int invoke_closure(closure *c)
{
return c->f(c->env.a, c->env.b);
}
Run Code Online (Sandbox Code Playgroud)
最后,用法看起来像
int main(void)
{
closure c;
make_adder(2, 1, &c);
printf("The answer is %d.\n", invoke_closure(&c));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出
The answer is 3.
虽然简短的回答是"不",但有办法完成你想做的事情.
要记住的第一件事是add需要两个参数.无论你做什么,你都必须提供两个参数.
要记住的第二件事是,如果你想打电话,最终调用一个函数add(2, 1),你必须有存储或硬编码的值2,并1让他们的地方可以使用.
我能想到有几种方法可以做到这一点.
创建一个包装函数,调用add(2, 1)并让代码调用包装函数.
int add2And1()
{
return add(2, 1);
}
Run Code Online (Sandbox Code Playgroud)
然后add2And1在你的通话中使用.
创建依赖于全局数据的包装函数.在使用包装函数之前先设置全局数据.
int param1 = 0;
int param2 = 0;
int addParams()
{
return add(param1, param2);
}
Run Code Online (Sandbox Code Playgroud)
然后使用:
param1 = 2;
param2 = 1;
Run Code Online (Sandbox Code Playgroud)
在调用之前的代码中addParams.
int add(int a, int b) { return a + b; }
Run Code Online (Sandbox Code Playgroud)
不,你不能指向add具有指定参数值的指针.但是你可以这样做:
int add_2_1() { return add(2, 1); }
Run Code Online (Sandbox Code Playgroud)
但我不明白这有多大帮助......