簡體   English   中英

將函數指針返回到C中的嵌套函數

[英]Return function pointer to a nested function in 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)

史蒂夫,您對C函數的思維模式完全錯誤。

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

從您的代碼片段中,我可以推測您認為可以將函數的已編譯代碼復制到一塊內存中,然后再使用它。 這種東西聞起來像Lisp一樣,除非在Lisp中您也不會那樣做。

實際上,當您說“&isNot”時,您將獲得一個指向函數的指針。 復制指針指向的內存會適得其反-將可執行文件加載到內存中時,內存已初始化,並且不會更改。 無論如何,編寫someFunc()都會導致核心轉儲,因為無法執行具有someFunc行為的堆內存-這樣可以保護您免受各種病毒的侵害。

您似乎期望在C中實現閉包。根本不存在該實現。 與Lisp,Perl或Ruby不同,一旦退出該框架,C就無法保留該框架的元素。 即使在某些編譯器中允許使用嵌套函數,我敢肯定您不能從這些函數內部引用非全局變量。 閉包的關閉對象確實是存儲狀態並實現operator()的C ++對象,但這是一種完全不同的方法,您仍然必須手動執行操作。

更新: 是GCC文檔的相關部分。 查找“但是,只有在包含功能(在此示例中為hack)沒有退出的情況下,此技術才有效。”

您將無法以所需的方式執行此操作。 您有兩種選擇。

您可以使用宏:

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

您還可以嘗試其他方法,例如運行時的JITing函數,但是這些技術將取決於平台和體系結構。 這個解決方案很尷尬,但是純C語言並且可移植。

我正在使用GCC。

您可以使用以下標志打開嵌套函數:

-fnested-functions

當您編譯時。

我也從未聽說過C中的嵌套函數,但是如果gcc支持它,那么它將無法按您期望的方式工作。 您只是簡單地復制isNot的機器指令,並且在調用“ not”時將不包括“ original”的實際值。

您應該使用C ++類來實現一個函數對象 ,該對象存儲可以用“原始”值初始化的指針,並從“非”返回該類的實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM