[Funktionen in Structs] Wie Funktionspointer richtig in structs verwenden



  • Hallo c-community,

    Ich suche derzeit nach einem gutes Tutorial oder eine guten Erklärung, wie man Funktionspointer in structs richtig verwendet. Ich weiß bisher, dass Sie wie folgt deklariert werden:

    struct foo {
        int a;
        void (*workwithit)(struct foo *);
    }
    

    Wie spreche ich diese aber dann aber richtig an? Ist foo.workwithit(Foo) (wobei gilt: struct foo* Foo) der Aufruf für die Funktion, welche man vorher in der Variable hinterlegt hat?
    Dann müsste auch:

    void Testfunction(struct foo* Foo)
    {
        ...
    }
    
    struct foo* Foo;
    
    foo.workwihtit = Testfunction
    

    die entsprechende Zuweisung sein??

    Hoffe hier kann mir jemand ein gutes Tutorial oder eine eigene Erklärung geben.

    Danke
    mirrowwinger



  • Die Variable ist Foo (nicht foo). Und das ist auch noch ein Zeiger.

    Bei Zeigern auf struct gibt es den ->

    Foo->workwithit= Testfunction;
    ....
    (Foo->workwithit)(Foo);  // Aufruf
    

    Und der Member heißt workwithit 😉


  • Mod

    Deine Funktionszeigersyntax ist schon richtig. Aber wie du mit dem struct und der (nicht vorhandenen) Instanz des structs umgehst ist total falsch. Flüchtigkeitsfehler?

    Die Funktionszeiger hast du dir schon selber richtig zusammen gereimt. Ich will noch erwähnen, dass man anstatt der angenehmen Kurzschreibweise, die du benutzt, auch etwas ausführlicher sein kann, dann sieht man vielleicht besser, was passiert:

    void foo(int);
    
    // ...
    
    void (*ptr)(int);
    ptr = foo;   // Geht
    ptr = &foo;  // Geht auch
    ptr(2);      // Geht
    (*ptr)(2);   // Geht auch
    

    Und viel mehr gibt es dazu eigentlich nicht zu sagen, du scheinst es bereits verstanden zu haben. Vielleicht noch der offensichtliche Tipp, das Funktionszeiger und typedefs gut zusammen gehen.



  • Danke für die schnelle Antwort.

    mirrowwinger



  • Warum funktioniert folgende Deklaration nicht?

    typedef struct
    {
        void (*create)(pObject* Obj); // <- hier Fehler pobject unbekannt
        void (*free) (pObject Obj);
    } Object, *pObject;
    


  • Weil da Object und pObject noch unbekannt sind.

    Du brauchst da eine named struct



  • Weil da Object und pObject noch unbekannt sind.

    Du brauchst da eine named struct



  • Dir dürfen beim einmaligen Durchlesen von deinem Code keine unbekannten Bezeichner vorkommen.
    pObject wird erst zwei Zeilen tiefer bekannt gemacht.

    Sorry für das Doppelpost. Busfahren und Handytastatur sind nicht ganz kompatibel. 🙄



  • könntest du da ein kurzes Beispiel geben, wie ich dies tun kann?

    ok so weit bin ich (noch nicht optimiert):

    struct Object
    {
        void (*create)(struct Object** Obj)
        void (*free)(struct Object* Obj)
    }
    

    Ich weiß mit den 2 mal * ist nicht so gut, aber bisher habe ich noch keine besser Möglichkeit gefunden. Vieleicht hat ja jemand einen anderen Vorschlag. Es fehlt auch noch die nachträgliche Definition von pObject.



  • Wie würdest du es denn ohne typedef machen?

    Hinter dem struct kommt ein Bezeichner.

    Dann hast du eine named struct.
    So wie bei verketteten Listen auch.

    Und statt pObject schreibst du dann struct Bezeichner *



  • oh editieren und Beitrag kamen wohl gleichzeitig.



  • mirrowwinger schrieb:

    Ich weiß mit den 2 mal * ist nicht so gut

    Lass dir nichts einreden.

    aber bisher habe ich noch keine besser Möglichkeit gefunden.

    Alternative:

    Object *(*create)();
    

    Das sind effektiv die zwei Möglichkeiten, die du hast ("Rückgabe" über globale Variablen geht theoretisch auch, lass ich aber aus offensichtlichen Gründen weg.)



  • Das typedef kannst du wieder davor setzen un Object und pObject dahinter.
    Nur innerhalb der struct musst ohne das typedef auskommen.



  • @Bashar: danke ist auch eine gute Variante.

    @DirkB: meinst du das so:

    typedef struct Object
    {
        struct Object* (*create)();  //nach Bashar
        void (*free)(struct Object* Obj);
    }Object, * pObject;
    

    [Edit1]Beim Kompilieren habe ich jetzt Fehler, dass struct Object* und pObject nicht als gleichwertig angesehen wird.[/Edit1]
    So lässt es sich kompilieren.


Anmelden zum Antworten