2016-01-24 198 views
7

我寫了一些代碼來知道函數指針是如何工作的。 我在一些IDE上運行以下C++代碼,結果是一樣的。C++中函數指針的指針

#include "stdafx.h" 

int *function(){ 
    static int a=1; 
    return &a; 
} 
typedef struct{ 
    int *(*pt_1)(); 
    int *(*pt_2)(); 
}x_t; 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    x_t s; 
    s.pt_1 = function; 
    s.pt_2 = &function; 

    printf("%x\n",s.pt_1); //Result: 0x013011a9 
    printf("%x\n",*s.pt_1); //Result: 0x013011a9 
    printf("%x\n",**s.pt_1); //Result: 0x013011a9 
    printf("%x\n",s.pt_1()); //Result: 0x01307000 
    printf("%x\n",*s.pt_1()); //Result: 1 

    printf("%x\n",s.pt_2); //Result: 0x013011a9 
    printf("%x\n",*s.pt_2); //Result: 0x013011a9 
    printf("%x\n",**s.pt_2); //Result: 0x013011a9 
    printf("%x\n",s.pt_2()); //Result: 0x01307000 
    printf("%x\n",*s.pt_2()); //Result: 1 

    return 0; 
} 

我的問題:

    1. 爲什麼s.pt_1 == s.pt_2 == *s.pt_1 = **s.pt_1
  • 凡地址是否s.pt_1()點?它在哪裏找到內存?
+3

1,請參閱[this](http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-function-pointer-happen)。 2. operator()調用函數,所以你正在處理它的返回指針。 – LogicStuff

+1

由'%x'打印函數指針會調用未定義的行爲,因爲地址可能不適合'int'。使用'printf(「%p \ n」,(void *)s。' –

+0

我在這裏找到了第二個問題的答案[內存中的內存是否存儲在內存中的返回值?](http://stackoverflow.com/questions/5472008/where-in-memory-are-return-values -stored式存儲器) –

回答

4

與使用數組名稱類似,使用函數名稱會使其衰減爲最輕微的挑釁指針。

s.pt_1 = function;  

這裏function衰變成指向函數的指針。

s.pt_2 = &function; 

在這裏,您實際上將函數的地址與第一種情況的結果相同。

printf("%x\n",s.pt_1); //Result: 0x013011a9 
printf("%x\n",*s.pt_1); //Result: 0x013011a9 
printf("%x\n",**s.pt_1); //Result: 0x013011a9 

在第一行pt_1是指向一個功能,並且顯示存儲在指針的地址。

在第二行,您取消引用指針並訪問函數本身。當傳遞給一個函數時,哪些衰變成指針。

在第三行中,您取消引用指針以獲取該函數,然後在與另一個*一起使用該函數時衰減爲指針。第二個星號產生的值在傳遞給函數時會再次衰減爲指針。等

1

的問題是,你不能根本做任何一個「函數對象」 ...... C++只管理「指針的功能」。

因此,一個函數將隱式衰減爲指向函數的指針以供任何用途......無論您放在它前面有多少個*

類似的情況發生在數組中,它們隱含地衰減爲指向第一個元素的指針,不同之處在於您可以對數組執行一些操作(例如sizeof),即使這對函數也是禁止的。

鑑於比在C++中沒有(便攜式)方法在運行時創建新函數,不能操縱函數對象的限制並不重要。您只能處理指向現有函數的指針......