2008-09-02 130 views
1

由于标题已经声明,我试图声明一个嵌套函数并返回一个指向该函数的指针。我希望这个函数'不'返回一个新的函数指针,它将返回任何原始函数的否定。返回函数指针指向嵌套函数C

以下是我有:

someType not(someType original) { 
    int isNot(ListEntry* entry) { 
     return !original(entry); 
    } 

    someType resultFunc = calloc(1024, 1); 
    memcpy(resultFunc, &isNot, 1024); 

    return resultFunc; 
} 

SOMETYPE被定义为:

typedef int(*someType)(ListEntry* entry) 

回答

0

我使用GCC。

您可以通过使用该标志打开嵌套函数:

-fnested-functions 
当你编译

0

我也从来没有听说过C中的嵌套函数,但是如果gcc支持它,这不会按照你期望的方式工作。您只是简单地复制isNot的机器指令,并且在调用“not”时不包括“original”的实际值。

您应该使用C++类来实现,它存储一个指针,您可以使用“original”值初始化该指针,并从“not”返回此类的一个实例。

19

史蒂夫,你对C函数的完全错误的心理模型。

someType resultFunc = calloc(1024, 1); 
memcpy(resultFunc, &isNot, 1024); 

从您的代码片段,我可以推测,你认为你可以复制功能的编译代码到的内存块,然后再用它。 Lisp的这种东西闻起来,除非在lisp中你不这样做。

事实上,当你说“& isNot”时,你会得到一个指向函数的指针。复制指针指向的内存会适得其反 - 当您将可执行文件加载到内存中时,内存被初始化,并且不会改变。在任何情况下,编写someFunc()都会导致核心转储,因为堆内存behing someFunc无法执行 - 这可以保护您免受各种病毒的侵害。

你似乎期待在C中实现闭包。这个实现根本就不存在。与Lisp或Perl或Ruby不同,C在退出该框架后无法保留堆栈框架的元素。即使嵌套函数在某些编译器中是允许的,我相信你不能从这些函数内部引用非全局变量。关闭关闭的事情确实是存储状态并实现operator()的C++对象,但它是一种完全不同的方法,并且您仍然必须手动执行操作。

更新:here是GCC文档的相关部分。寻找“但只有包含函数(在本例中为hack)不会退出,这种技术才有效。”

+0

感谢您的链接,我最喜欢的引用是“如果你试图在包含函数退出后通过它的地址调用嵌套函数,所有的地狱都会崩溃。” – luke 2010-05-23 18:56:40

1

你不能以你想要的方式做到这一点。你有几个备选方案。

您可以使用宏:

#define FN_NOT(F) !F 
#define notSomeFunc FN_NOT(someFunc) 
... 
x = notSomeFunc(entry); 

但我怀疑你希望能够通过周围的否定函数来取函数指针等功能,这样就不会工作。

你可以改变你的接口来接受一些额外的信息,例如

struct closure { 
    void *env; 
    int (*f)(struct closure* extra, ListEntry*); 
}; 

static int isNot(struct closure* extra, ListEntry *entry) { 
    someType original = extra->env; 
    return !original(entry); 
} 

struct closure not(someType original) { 
    closure rv; 
    rv.env = original; 
    rv.f = &isNot; 
    return rv; 
} 

,然后用它喜欢:

struct closure inverse_fn; 
inverse_fn = not(&fn); 
if(inverse_fn.f(&inverse_fn, entry)) { 
    ... 
} 

还有其他的东西,你可以在运行时尝试,如JIT编译功能,但这些技术将取决于平台和架构。这个解决方案很尴尬,但纯C和便携。