Definieren einer Funktion, die einen Funktionszeiger zurückgibt, der auch einen Funktionszeiger ohne typedefs zurückgibt




function function-pointers (3)

Der Rückgabetyp der Funktion get_pfn ist -

void (*) ();

Der Typ von &get_pfn ist also -

void (*(*)(int))()

Diese Funktion gibt nun diesen Typ zurück, daher lautet die Signatur:

void (*(*(foo)())(int))()

Sie können dies überprüfen, indem Sie dies in cdecl.org

Ich versuche, Funktionszeiger wirklich zu verstehen, ohne typedef aber kann nicht scheinen, dieses zu erhalten. Ich verstehe nicht, welche Signatur benötigt wird, um zu vermitteln, dass ich einen Zeiger auf einen Zeiger auf eine Funktion zurückgebe.

#include <stdio.h>

void odd()  { printf("odd!\n");  }
void even() { printf("even!\n"); }

void (*get_pfn(int i))()
{
    return i % 2 == 0 ? &even : &odd;
}

__SIGNATURE__
{
    return &get_pfn;
}

int main()
{
    get_pfn_pfn()(1)();
    get_pfn_pfn()(2)();
    return 0;
}

Was muss __SIGNATURE__ sein, damit dies funktioniert?


Es muss einen Funktionszeiger auf eine Funktion zurückgeben, die einen int und einen Funktionszeiger zurückgibt:

void (*(*get_pfn_pfn(void))(int))(void) {
    return &get_pfn;
}

mehr Zeilen:

void (*
        (*
             get_pfn_pfn(void)  // this is our function
        )(int i) // this is get_pfn(int)
     )(void)  // this is odd() or even()
{
    return &get_pfn;
}

Die void s kann weggelassen werden. In diesem Fall zeigt der Funktionszeiger auf eine Funktion, die eine unbekannte Anzahl von Parametern akzeptiert. Welches ist nicht was Sie wollen. Um einen Funktionszeiger auf eine Funktion zu deklarieren, die keine Argumente akzeptiert, sollten Sie in der Liste der Funktionsparameter void hinzufügen. Genauso ist es am besten, get_pfn in void (*get_pfn(int i))(void) zu ändern. Versuchen Sie beispielsweise, get_pfn(1)("some arg", "some other arg"); . Der AC-Compiler gibt keine Warnung aus, da empty () unbekannte Argumente angeben. Um zu sagen, dass die Funktion keine Argumente akzeptiert, müssen Sie (void) .

Für viele Sequenzen von geschweiften Klammern, insbesondere ))( in Funktionszeigern, ist das Parsen schwierig. Deshalb bevorzugen viele typedefs für Funktionszeiger oder Typen:

typedef void get_pfn_func_t(void);    
get_pfn_func_t *get_pfn(int i) {
    return i % 2 == 0 ? &even : &odd;
}

typedef get_pfn_func_t *get_pfn_pfn_func_t(int i);
get_pfn_pfn_func_t *get_pfn_pfn(void) {
    return &get_pfn;
}

es geht hier entlang:

void (*(*get_pfn_pfn(void))(int))()




function-pointers