2016-01-24 40 views
7

Napisałem kod informujący o działaniu wskaźnika funkcji. Uruchomiłem następujący kod C++ na niektórych IDE, wyniki są takie same.Wskaźnik do wskaźnika funkcji w 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; 
} 

Moje pytania:

    1. Dlaczego s.pt_1 == s.pt_2 == *s.pt_1 = **s.pt_1?
    1. Jeżeli adres ma punkt s.pt_1() do? Gdzie znajduje się w pamięci?
+3

1, zobacz [to] (http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-unction-pointer-happen). 2. 'operator()' wywołuje funkcję, więc pracujesz z jej zwróconym wskaźnikiem. – LogicStuff

+1

Wskaźniki funkcji drukowania według '% x' wywołują niezdefiniowane zachowanie, ponieważ adresy mogą nie pasować do' int'. Użyj 'printf ("% p \ n ", (void *) s.pt_1); ' –

+0

Znalazłem odpowiedź na drugie pytanie tutaj [Gdzie w pamięci są zwracane wartości przechowywane w pamięci?] (http://stackoverflow.com/questions/5472008/where-in-memory-are-return-values -stored-in-memory) –

Odpowiedz

4

Podobnie jak przy użyciu nazwy tablicy, użycie nazwy funkcji spowoduje jej rozpad na wskaźnik przy najmniejszej prowokacji.

s.pt_1 = function;  

Tutaj function rozpada się na wskaźnik do funkcji.

s.pt_2 = &function; 

Tutaj faktycznie przyjmuje się adres funkcji, co skutkuje tym samym wskaźnikiem, co w pierwszym przypadku.

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

Na pierwszej linii pt_1 jest wskaźnik do funkcji, i wyświetlany jest adres przechowywany we wskaźniku.

W drugim wierszu usuwasz wskaźnik i uzyskujesz dostęp do samej funkcji. Który rozpada się na wskaźnik po przejściu do funkcji.

W trzecim wierszu usuwa się wskaźnik, aby uzyskać funkcję, która następnie zanika do wskaźnika, gdy używa się go z innym *. Druga gwiazda daje wartość, która ponownie rozpada się na wskaźnik po przekazaniu do funkcji. Itd.

1

Problem polega na tym, że nie można po prostu zrobić coś z „obiektu funkcja” ... C++ tylko udaje „wskaźniki funkcjonować”.

Z tego powodu funkcja domyślnie rozpada się na wskaźnik funkcji do dowolnego użytku ... Nie ma znaczenia, ile przedłożysz przed nią *.

Coś podobnego dzieje się z tablicami, gdzie domyślnie rozpadają się na wskaźnik do pierwszego elementu, z tą różnicą, że można wykonać pewne operacje na tablicach (na przykład sizeof), nawet jeśli jest to zabronione z funkcjami.

Dany niż w C++ nie ma (przenośnego) sposobu tworzenia nowych funkcji w czasie wykonywania, ograniczenie nieumiejętności manipulowania obiektami funkcyjnymi nie jest tak naprawdę ważne. W każdym razie możesz radzić sobie tylko z wskaźnikami do istniejących funkcji ...