Frage an c, function-pointers – C-Syntax für Funktionen, die Funktionszeiger zurückgeben

34

Betrachten Sie die folgenden typedefs:

typedef int (*f1)(float);
typedef f1 (*f2)(double);
typedef f2 (*f3)(int);

f2 ist eine Funktion, die einen Funktionszeiger zurückgibt. Das selbe mitf3, aber die Art der Funktion, auf die der Zeigerf3 kehrt zurück, istf2. Wie kann ich definierenf3 ohne die typedefs? Ich weiß, dass typedefs die sauberere und verständlichere Art der Definition sindf3. Ich beabsichtige hier jedoch, die C-Syntax besser zu verstehen.

Und für zusätzliches Guthaben machen Sie f3 __stdcall, f2 __cdecl und f1 __fastcall Gur
C oder C ++? Weil C ++ einige einfachere Möglichkeiten hat, solche Dinge auszudrücken. Puppy
Sie sollten verwendenstd::function stattdessen ... den gleichen Grund, den Sie verwenden solltenstd::vector anstattnew/delete. Inverse

Deine Antwort

6   die antwort
4

die Rechts-Links-Regel:

Die "Rechts-Links" -Regel ist eine ganz normale Regel zum Entschlüsseln von C-Deklarationen. Dies kann auch beim Erstellen hilfreich sein.

7

Wie beim typedef platzieren nur Sie Ihre Funktionsdefinition anstelle ihres Namens.

Hier ist wief2 würde aussehen wie:

typedef int (*(*f2)(double))(float);

Du kannst tunf3 als übung, da ich davon ausgehe, dass dies hausaufgaben sind;)

Übrigens,int (*(*f3(double))(float))(int) { return 0; } definiert die Funktion mit dem Typ, den ich suche. Vielen Dank. keveman
Die Antwort, die Sie geben, ist über eine Google-Suche verfügbar. Die Syntax für mehr als eine Ebene (Funktionsrückgabe Funktionszeiger Rückgabe Funktionszeiger) ist jedoch nicht sehr einfach zu finden. Und der Bezug zu den Hausaufgaben war nicht gerechtfertigt. keveman
Mr. Downvoter benötigt bessere C-Parsing-Fähigkeiten. Blindy
@ keveman- Diese Definition stimmt nicht mit Ihrer ursprünglichen Beschreibung überein. Geben Sie es in cdecl.org ein und Sie erhalten eine detaillierte Beschreibung. Ich denke, Ihre Funktionsargumente müssen in der Reihenfolge seinint->double->float. bta
0

Benutzenstd::function:

typedef std::function<int(float)> f1;
typedef std::function<f1(double)> f2;
typedef std::function<f2(int)>    f3;

oder

typedef std::function<std::function<std::function<int(float)>(double)>(int)> f3;
5

Tu es einfach nicht. Es kann getan werden, aber es wird sehr verwirrend sein. Typedefs erleichtern das Schreiben und Lesen dieser kurzen Code.

Eine Funktionf Das akzeptiert keine Argumente und gibt einen Funktionszeiger zurückint (*)(float) wäre wahrscheinlich so etwas wie (ungetestet):

int (*f())(float);

Im Übrigen müssen Sie nur noch Klammern hinzufügen, bis es aussieht wie "lisp".

+1: Tu es einfach nicht. Die lispische Erscheinung von John Bodes Antwort ist nichtssagend. David Hammen
13

In C ++ kann das Wunder der Vorlagen dies ein bisschen einfacher machen.

#include <type_traits>

std::add_pointer<
    std::add_pointer<
        std::add_pointer<
            int(float)
        >::type(double)
    >::type(int)
>::type wow;
@Macmade: Wenn Sie C ++ markieren, erhalten Sie eine C ++ - Antwort. Puppy
Dies ist vielleicht sauberer, als überhaupt keine Hilfsmittel zu verwenden (auch nichttypedef oderadd_pointer), aber dietypedef Ansatz ist noch sauberer (IMHO). David Hammen
Die Frage betraf die C-Syntax, auch wenn der Beitrag mit C ++ getaggt war, daher ist er meiner Meinung nach nicht relevant ... Aber eine nette Antwort nebenbei. :) Macmade
+1 für das "wow" :-) Eitan T
114

Beginnen Sie mit Ihrer Erklärung fürf1:

int (*f1)(float);

Sie wollenf2 ein Zeiger auf eine zurückkehrende Funktion seinf1, also ersetzef1 in der obigen Erklärung mit der Erklärung fürf2:

int (*      f1     )(float);
            |
      +-----+-----+
      |           |
      v           v
int (*(*f2)(double))(float);

Die Erklärung lautet wie folgt

        f2                   -- f2
       *f2                   -- is a pointer
      (*f2)(      )          -- to a function
      (*f2)(double)          --   taking a double parameter
     *(*f2)(double)          --   returning a pointer
    (*(*f2)(double))(     )  --   to a function
    (*(*f2)(double))(float)  --     taking a float parameter
int (*(*f2)(double))(float)  --     returning int

Sie wiederholen den Vorgang fürf3:

int (*(*    f2    )(double))(float);
            |
        +---+----+
        |        |
        v        v
int (*(*(*f3)(int))(double))(float);

was liest sich als

          f3                           -- f3
         *f3                           -- is a pointer
        (*f3)(   )                     -- to a function
        (*f3)(int)                     --   taking an int parameter
       *(*f3)(int)                     --   returning a pointer
      (*(*f3)(int))(      )            --   to a function
      (*(*f3)(int))(double)            --     taking a double parameter
     *(*(*f3)(int))(double)            --     returning a pointer
    (*(*(*f3)(int))(double))(     )    --     to a function
    (*(*(*f3)(int))(double))(float)    --       taking a float parameter
int (*(*(*f3)(int))(double))(float);   --       returning int
+1, da dies wirklich die ursprüngliche Frage beantwortet, die über die richtige Syntax in C war ... Macmade
Danke, John! Ich habe mich gefragt, wo Sie das gelernt haben? Gibt es ein gutes Buch, das es erklärt? Tim
Wenn dein Hammer C ist, sieht alles wie ein Daumen aus ... Spook
Diese Antwort sollte in großen Mengen gedruckt und in Schulen für Computertechnik verbreitet werden. Dies ist der einfachste und beste Weg, die Deklarationssyntax für Funktionszeiger zu verstehen. Vielen Dank, John Bode! Ki Jéy
@Tim: Es geht hauptsächlich darum, die Deklarationssyntax zu verstehen, was in den meisten Referenzen leider nicht sehr gut erklärt wird. Es hat eines Tages einfach "geklickt", und plötzlich ergaben haarige Äußerungen Sinn. John Bode

Verwandte Fragen