我开始学习函数式编程,并希望看看我是否可以使用C语言中的闭包。为了从Wikipedia - Closures重现第一个示例,我编写了以下代码:
#include <stdio.h>
void closure (int(** f)(int), int *x) {
int fcn(int y) {
return *x + y;
};
*f = fcn;
}
int main()
{
int x = 1;
int(* f)(int);
closure(&f, &x);
printf("%d", f(2));
return 0;
}
它被编译(gcc 4.8.2。在Ubuntu 14.04。)并且它有效,它打印出3.由于缺乏我在C的专业知识(只有大学的基础课程),我的问题是,是否有一些认真的事情这段代码有问题吗?我被教导功能定义应该是全局的,我从来没有想过这会起作用......
编辑: 当我改变主要功能时,为什么呢?
int main()
{
int x = 1;
int(* f)(int);
closure(&f, &x);
printf("%d", f(2));
printf("%d", f(3)); // the only difference
return 0;
}
我收到Segmentation故障?
答案 0 :(得分:4)
您的代码有效,因为gcc具有支持嵌套函数的语言扩展名。
但是,在标准C中,您无法在另一个函数中定义函数。
如果你试图在包含函数退出后通过其地址调用嵌套函数,那么所有的地狱都会破裂。如果您尝试在包含范围级别退出后调用它,并且如果它引用了一些不再在范围内的变量,您可能会很幸运,但冒风险并不明智。但是,如果嵌套函数没有引用超出范围的任何内容,那么您应该是安全的。
答案 1 :(得分:2)
首先,您的程序调用未定义的行为。这是因为函数fcn
中定义的函数closure
是本地函数。 fcn
返回后closure
不再存在。所以printf
来电
printf("%d", f(2));
通过调用f(2)
来调用未定义的行为,因为f
指向不在范围内的函数fcn
。
C
语言没有闭包,因为C
中的函数不是第一类对象。这意味着函数不能传递给其他函数或者不能从函数返回。实际传递或返回的是指向它的指针。
请注意,嵌套函数和闭包之间存在差异。您看到的是nested function的GCC扩展程序。它不是C标准的一部分。