2011-04-30 15 views
6

可能重複:
How does dereferencing of a function pointer happen?值的函數/ C++

如果我們有

void f() { 
    printf("called"); 
} 

然後將以下代碼將導致 「calledcalled」 輸出:

f(); 
(*f)(); 

我真的不明白這是如何工作的... *ff有什麼區別?你爲什麼要用後一種語法調用一個函數?

+1

這需要有兩個問題,一個關於C,一個對C++的,因爲他們有微妙的不同的規則(儘管最終相同的行爲)。 – 2011-04-30 20:49:58

回答

6

有兩種方法來調用一個函數在C++:

按名稱:

f(); 

通過函數指針:

typedef void (*fptr_t)(); 
fptr_t fptr = &f; 
(*fptr)(); 

現在,使用地址運算符函數名稱(&f)顯然會創建一個函數指針。但是,當滿足某些條件時,函數名可以隱式轉換爲函數指針。所以上面的代碼可以寫成:

typedef void (*fptr_t)(); 
fptr_t fptr = f; // no address-of operator, implicit conversion 
(*fptr)(); 

你的第二個例子做的正是這一點,但使用臨時變量來保存函數指針,而不是一個名爲局部變量。

我更喜歡在創建函數指針時使用address-of,意思就更清晰了。

相關說明:如果提供函數指針,函數調用運算符將​​自動解引用函數指針。所以,這也是合法的。

typedef void (*fptr_t)(); 
fptr_t fptr = &f; 
fptr(); 

這與模板非常有用,因爲相同的語法運作的,你是否有一個函數指針或仿函數(對象實施operator())傳入

而且沒有捷徑可與指向成員的指針,那裏你需要顯式地址和取消引用操作符。


在C,@Mehrdad explains that all function calls use a function pointer.

+0

我希望我們會在C++ 0x中看到更加微妙的問題,包括lambda表達式和所有... – Mehrdad 2011-04-30 22:06:17

6

第一個是第二個語法糖。第二個很明顯,你是通過一個指針進行調用的,它主要用於函數指針而不是常規函數,以使這種區別更加明顯。

+0

那麼第二個隱式地將指針指向'f',然後通過那個調用函數? – 2011-04-30 20:13:19

+2

@Matti:不,第二個是* dereferencing *指針並調用函數,這是第一個*隱含*做的。 (*符號有幾個含義 - 除了乘法之外,它可以是解引用*運算符*和指針*聲明*。不要讓它們混淆。) – Mehrdad 2011-04-30 20:14:03

+0

f是一個地址。 (* f)()是對該地址的函數調用。 – 2011-04-30 20:14:43

2

正如陣列型幾乎完全等同於相應指針到單元類型,一個功能類型是完全等同於相應指針到功能類型:

void (*func1)() = f; // function type -> pointer-to-function type 
void (*func2)() = &f; // pointer-to-function type -> pointer-to-function type 

並且還

void (*func)() = ...; 
func();    // pointer-to-function type + function-call operator 
(*func)();   // function type + function-call operator 

所以,在

(*f)(); 

你提領f(隱式轉換爲&f),然後應用函數調用操作符。