2016-11-17 38 views
1

我一直在從函數參數中獲取函數指針。 下面是我想要做的一個例子。如何從C函數參數中檢索函數?

int a(int I) 
{ 
    return I*I; 
} 

void get_a(int(*R)(int)) 
{ 
    R = &a; 
} 

int main() 
{ 
    int(*function)(int) = NULL; 

    printf("function a=%p\n", a); 

    get_a(function); 
    printf("function a=%p\n", &function); // Is never the right address. 

    return 0; 
} 

搜索網沒有幫助,我只能找到傳遞函數爲參數的例子,所以我放棄了,並試圖通過自己解決這個問題。

+0

這與「如何從函數參數中檢索int」沒有區別。首先解決這個問題,你也會理解這個問題。 –

+0

您的函數get_a()完全不做任何事情,因爲它所做的只是將其分配給本地變量,然後不返回任何內容。一個好的編譯器甚至可以完全優化它。 –

回答

2

這裏有兩個問題。

首先,你的函數正在修改一個局部變量,所以結果永遠不會反映到調用者中。您需要傳遞函數指針變量的地址,然後有get_a接受指針函數指針。通過傳遞變量的地址,您可以解除引用並修改它。

的第二個問題是,你的第二個printf正在打印地址function而不是它的價值。傳入價值。

void get_a(int(**R)(int)) 
{ 
    *R = &a; 
} 

int main() 
{ 
    int(*function)(int) = NULL; 

    printf("function a=%p\n", (void *)a); 

    get_a(&function); 
    printf("function a=%p\n", (void *)function); 

    return 0; 
} 

結果:

function a=0x400498 
function a=0x400498 

還要注意投給void *。傳遞指向printf以通過%p打印的指針是極少數情況下需要投射到void *,否則可能會遇到未定義的行爲。

+0

感謝一個快速回復的例子,正是我需要的:)。一直嘗試與額外*和&的幾個組合,但顯然沒有這個。 –

+0

@PuzzlingProgrammer很高興我能幫到你。如果您覺得它有用,請隨時[接受此答案](http://stackoverflow.com/help/accepted-answer)。 – dbush

+0

在這兩種情況下,應該是'printf(「...%p ...」,(void *)whatever),或者行爲未定義。 (這不僅僅是因爲我們正在處理指向函數的指針;'printf'是可變參數,所以沒有自動轉換指針;%p的參數必須轉換爲'void *',除非它的類型已經是'[const] void *'或(僅在C11中)'[const] char *'。) – zwol

3

第一個問題是你打印一個指針指向function指針,而不是它的值;它永遠不會給你正確的地址。

有了這個問題,剩下的問題是R是一個按值傳遞的函數指針。在get_a內對其進行的任何更改都是該函數的局部功能,並不代表main內的function的值。

有兩種解決這個問題:

  • 使get_a返回函數指針,並在main分配function = get_a(),或
  • 傳遞函數指針的指針進入get_a,並與非關聯分配,即使用您用於非函數指針的相同技術。

這裏是你如何實現第二種方法:

void get_a(int(**R)(int)) { 
    *R = a; 
} 
... 
get_a(&function); 

Demo.

注: ISO C不允許函數指針轉化爲void*,這是需要具有打印%p。不過,我認爲你是在爲調試目的而做這件事。

+0

第一種方法的解決方案應該是'int(* get_a())(int){return&a;}'。亂。 –

+0

好奇:ISO C是否允許'uintmax_t(或uintptr_t)p =(cast_to_type)function_ptr''?即使目標類型對於所有'function_ptr'都不夠寬? – chux

+1

@chux好問題,我不知道。 – dasblinkenlight