2016-11-17 1 views
1

Ich bin stecken in einen Funktionszeiger von einem Funktionsparameter zurück zu bekommen. Hier ist ein Beispiel für das, was ich versuche zu tun.Wie Sie eine Funktion von einem Funktionsargument in C abrufen?

int a(int I) 
{ 
    return I*I; 
} 

void get_a(int(*R)(int)) 
{ 
    R = &a; 
} 

int main() 
{ 
    int(*function)(int) = NULL; 

    printf("function a=%p\n", a); 

    get_a(function); 
    printf("function a=%p\n", &function); // Is never the right address. 

    return 0; 
} 

Suche im Netz nicht helfen, ich nur Beispiele für eine Funktion als Parameter finden konnte, so habe ich aufgegeben und versuchte, dieses Problem allein zu lösen.

+0

Dies unterscheidet sich nicht von "wie ein Int von einem Funktionsargument abgerufen wird". Löse dieses Problem zuerst und du wirst das auch verstehen. –

+0

Ihre Funktion get_a() tut genau nichts, weil sie nur einer lokalen Variablen zuweist und dann nichts zurückgibt. Ein guter Compiler könnte es sogar vollständig optimieren. –

Antwort

2

Sie haben zwei Problem hier.

Zuerst ändert Ihre Funktion eine lokale Variable, so dass das Ergebnis niemals im Aufrufer reflektiert wird. Sie müssen die Adresse Ihrer Funktionszeigervariable übergeben und dann get_a einen Zeiger-zu-Funktionszeiger annehmen lassen. Indem Sie die Adresse der Variablen übergeben, können Sie sie dereferenzieren und ändern.

Das zweite Problem ist, dass Ihre zweite printf druckt die Adresse von function statt dessen Wert. Übergeben Sie den Wert.

void get_a(int(**R)(int)) 
{ 
    *R = &a; 
} 

int main() 
{ 
    int(*function)(int) = NULL; 

    printf("function a=%p\n", (void *)a); 

    get_a(&function); 
    printf("function a=%p\n", (void *)function); 

    return 0; 
} 

Ergebnis:

function a=0x400498 
function a=0x400498 

Auch die Besetzung zu void * beachten. Das Übergeben eines Zeigers an printf, der über %p gedruckt werden soll, ist einer der seltenen Fälle, in denen das Umwandeln in eine void * erforderlich ist, da andernfalls ein undefiniertes Verhalten auftreten könnte.

+0

Vielen Dank für eine schnelle Antwort mit einem funktionierenden Beispiel, genau was ich brauchte :). Ich habe mehrere Kombinationen mit extra * und & versucht, aber anscheinend nicht diese. –

+0

@PuzzlingProgrammer Ich bin froh, dass ich helfen konnte. Fühlen Sie sich frei, diese Antwort zu akzeptieren (http://stackoverflow.com/help/accepted-answer), wenn Sie es nützlich fanden. – dbush

+0

Das sollte 'printf (" ...% p ... ", (void *) was auch immer)' in beiden Fällen sein, oder das Verhalten ist nicht definiert. (Dies liegt nicht nur daran, dass es sich um Zeiger auf Funktionen handelt; "printf" ist variadisch, daher gibt es keine automatische Umwandlung von Zeigern; ein Argument für% p muss in "void *" umgewandelt werden, es sei denn, sein Typ ist bereits vorhanden ist '[const] void *' oder (nur in C11) '[const] char *'.) – zwol

3

Das erste Problem ist, dass Sie einen Zeiger auf function Zeiger, nicht seinen Wert drucken; es wird dir nie die richtige Adresse geben.

Mit diesem Problem aus dem Weg, ist das verbleibende Problem, dass R ist ein Funktionszeiger durch Wert übergeben. Alle Änderungen daran innerhalb sind lokal für die Funktion und spiegeln nicht den Wert function innerhalb main wider.

Sie haben zwei Lösungen für dieses Problem:

  • get_a Rückkehr Funktionszeiger machen und weisen function = get_a() im main oder
  • Geben Sie einen Zeiger Zeiger in get_a, funktionieren und mit dereferenzieren zuweisen, dh Verwenden Sie die gleiche Technik, die Sie für Nichtfunktionszeiger verwenden.

Hier ist, wie Sie den zweiten Ansatz implementieren:

void get_a(int(**R)(int)) { 
    *R = a; 
} 
... 
get_a(&function); 

Demo.

Hinweis: ISO C verbietet Konvertierung von Funktionszeiger auf void*, das ist das, was mit drucken ist erforderlich %p. Ich nehme an, dass Sie es für Debugging-Zwecke tun.

+0

Die Lösung für den ersten Ansatz sollte 'int (* get_a()) (int) {return & a;}' sein. Unordentlich. –

+0

Neugierig: Erlaubt ISO C 'uintmax_t (oder uintptr_t) p = (Cast_to_type) function_ptr''? auch wenn der Zieltyp nicht für alle 'function_ptr' ausreichend ist? – chux

+1

@chux Gute Frage, ich habe keine Ahnung. – dasblinkenlight

Verwandte Themen