2012-02-17 110 views
22
#include<stdio.h> 
#include<stdlib.h> 

int fun1() 
{ 
    printf("I am fun1."); 
    return 0; 
} 

int fun2(int fun()) 
{ 
    fun(); 
    return 0; 
} 

int main() 
{ 
    fun2(fun1); 
    return 0; 
} 

上述程序可以運行。就我而言,我可以理解int fun2(int (*fun)()),但我不知道int fun2(int fun())是如何工作的。謝謝。關於指針函數聲明中的函數

+3

這在C,C99嚴格,C++ 03和C++ 11中有效。我很驚訝。 – 2012-02-17 11:36:50

回答

32

當寫int fun2(int fun()),參數int fun()轉換成int (*fun)(),變得完全等效於這樣的:

int fun2(int (*fun)()); 

更famiiar轉換髮生在陣列的情況下,當你聲明爲函數參數。例如,如果您在此:

int f(int a[100]); 

即使在這裏的參數類型轉換成int*,它變成這樣:

int f(int *a); 

之所以功能類型和數組類型轉換爲函數指針類型和指針類型分別是因爲Standard不允許將函數和數組傳遞給函數,也不能從函數返回函數和數組。在這兩種情況下,他們衰退到他們的指針版本。

的C++ 03標準說,在§13.1/ 3(它是在C++ 11也相同),不同之處僅在於一個

參數的聲明是一個函數類型和其它是指向相同功能類型的指針是等效也就是說,函數類型被調整爲指向函數類型(8.3.5)的指針。

和更有趣的討論是在這裏:

+2

+1注意與數組的相似性。 – asaelr 2012-02-17 11:43:01

+4

很好的答案。此外,我不知道這個工作! – 2012-02-17 11:54:54

+0

謝謝。我一直困惑很久。 – dragonfly 2012-02-17 13:49:59

6

int fun2(int (*fun)())int fun2(int fun())完全一樣。當你從一個函數類型聲明一個函數參數時,編譯器就像它是一個指向相同函數類型的指針一樣使用它。

-3

尋找到它在一個較低的水平(和在基於x86架構):

int fun2(int fun()) 

INT樂趣()的地址被壓入堆棧並傳遞到FUN2()函數。

int fun2(int (*fun)()) 

INT樂趣()指針地址被壓入堆棧並傳遞到FUN2()函數。

結果是一樣的,除了第二個,通過引用傳遞fun()的地址,並且在第一個值中傳遞它。

+0

函數地址和函數指針地址有什麼區別?或者,你是什麼意思的短語「指針地址」? – 2012-02-17 11:42:09

+0

指針地址我的意思是*** p *。也就是指向函數地址的指針的地址。 – m0skit0 2012-02-17 11:44:47

+0

_ ** p_是什麼意思?這看起來像兩次可以被解除抑制的東西被解除引用兩次?指向函數的指針的地址可能類似於:int(* fnptr)(); int(** p)()= &fnptr;'但這個問題中沒有出現這種情況? – 2012-02-17 11:49:43

3

這兩個函數定義在C是等價的:

int fun2(int fun()) { ... } 

int fun2(int (*fun)()) { ... } 

在第一個函數中,參數被調整爲函數指針。見C標準的段落:

(C99,6.7.5.3p8)「的參數的聲明爲‘’函數返回類型‘’,應調整至‘’函數指針返回類型‘’,如在6.3 .2.1「。