2013-10-27 57 views
8

我有這兩個測試功能:爲什麼這兩個函數指針在C/C++中合法?

int apply_a(int (*fun)(int, int), int m, int n) { 
    return (*fun)(m,n); 
} 

int apply_b(int (*fun)(int, int), int m, int n) { 
    return fun(m,n); 
} 

他們似乎返回不同的東西,那麼爲什麼他們都產生相同的結果?

int add(int a, int b) {return a + b;} 

int res_a = apply_a(add, 2, 3); // returns 5 
int res_b = apply_b(add, 2, 3); // returns 5 

我會假設其中一個會返回指針地址或指針本身;而不是存儲在指針上的值...

那麼爲什麼要這樣做呢?

+2

因爲任一語法(帶或不帶星號)的有效期爲通過指針調用一個函數。第二種情況是一個調用(你可以通過括號和傳遞的參數來判斷)。 – StoryTeller

+10

這兩個都不錯。你應該使用'(*** fun)(m,n)'作爲一個三星程序員。 –

回答

7

由於C++在處理非成員函數的地址和使用指針指向它們時提供了語法糖。無論使用哪種

int someFunc(int); 

int (* someFuncPtr)(int) = someFunc; 

或:

int (* someFuncPtr)(int) = &someFunc; 

也有使用這種指針的語法糖,無論是通話

我們可以得到這樣的函數地址指向功能:

(*someFuncPtr)(5); 

或簡化語法:

someFuncPtr(5); 
+0

請記住,這同樣適用於靜態類方法(至少在我檢查過的Visual C++ 2012中)) – altariste

+0

這也適用於C嗎?還是僅適用於C++的糖規則? –

+0

C++爲「函數」類型引入了另一個符號:可以轉換爲「int(*)(int)」的「int(int)」。 'someFunc'具有類型'int(int)',而'&someFunc'具有類型'int(*)(int)'。 –

0

在C和C++的函數名也是指針的功能代碼。因爲任何指針都可以使用*來解引用它們,在函數指針的情況下,除了取消引用外,還可以使用其他參數,例如在apply_a的情況下。但是C和C++函數的有效調用僅僅是通過它們的名字來調用它們,這就是apply_b的情況。

+0

這不是名稱。 **任何**表達式是一個函數,而不僅僅是一個函數名稱,將被轉換爲指向該函數的指針。 –

1

這是因爲你沒有返回這些值的內存地址。 用指針調用函數不會改變它的值,它仍然調用函數。你可以做的是一種價值迴歸變量,然後獲得它的內存地址,如:

int result = fun(m,n); 
cout << "the result " << result << " pointing at " << &result << endl; 
6

(*fun)(m,n)相同fun(m,n)由於C和C++規則,轉換功能函數指針。

在C 2011中,規則是條款6.3.2.1 4:「A 函數指示符是具有函數類型的表達式。除了當它是的sizeof運算符的操作數時,_Alignof操作者,或一元&操作,功能指示器,類型爲「函數返回類型」被轉換爲具有類型「指針到一個表達函數返回類型「。在C++中,該規則是第4.3條。

請注意,函數指示符不僅僅是一個名稱函數的標識符。它可能是一個標識符,或者它可能是另一個表達式。例如,如果foo是函數的名稱,則它將自動轉換爲上述函數的指針。然後,由於foo是該函數的指針,因此*foo是函數。這意味着你可以這樣寫:

(*fun)(m,n) 

結果是fun被自動轉換爲指針,然後*計算的功能,然後*fun轉換回指針,那麼函數被調用。您可以繼續此操作並編寫:

(**************fun)(m,n) 

這與fun(m,n)相同。每個*都會再次生成該函數,但編譯器會自動將其轉換回指針。你可以永遠繼續這場戰鬥,但編譯器將永遠贏。

事實上,這些都具有同樣的效果:

(&fun)(m,n) 
(fun)(m,n) 
(*fun)(m,n) 
相關問題