2014-06-14 76 views
2

我開始學習函數式編程,想看看我是否能在與C.封逃脫爲了再現從Wikipedia - Closures我編寫了下面的代碼第一個例子:在C中關閉 - 這是否工作?

#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; 
} 

我得到分割故障?

回答

4

您的代碼有效,因爲gcc有一個支持嵌套函數的語言擴展。

但是,在標準C中,您不能在另一個函數中定義函數。

Gnu Nested Functions

如果試圖包含它的函數退出後通過其地址來調用嵌套函數,所有的地獄破散。如果您在包含範圍級別退出後嘗試調用它,並且如果它引用了一些不在範圍內的變量,那麼您可能很幸運,但採取這種風險並不明智。但是,如果嵌套函數沒有引用任何超出範圍的東西,則應該是安全的。

+0

謝謝你的回覆。我用一個不起作用的示例編輯了一個問題(對不起,以前沒有發佈它)。不應該有一些內存問題,如訪問局域變量超出範圍或類似的東西嗎? –

2

首先,您的程序會調用未定義的行爲。這是因爲功能closure中定義的功能fcn是本地的。一旦closure返回,fcn不再存在。所以printf呼叫

printf("%d", f(2)); 

通過調用f(2)因爲f指向功能fcn這是不是在範圍內調用未定義的行爲。

C語言沒有關閉,這是因爲C中的函數不是一流的對象。這意味着函數不能傳遞給其他函數,或者不能從函數返回。實際傳遞或返回的是指向它的指針。

請注意,嵌套函數和閉包之間有區別。你看到的是一個GCC擴展nested function。它不是C標準的一部分。