Zurückgebender Funktionszeigertyp

Lesezeit: 8 Minuten

Benutzeravatar von SE
SE

Oft finde ich die Notwendigkeit, Funktionen zu schreiben, die Funktionszeiger zurückgeben. Wann immer ich dies tue, verwende ich das grundlegende Format:

typedef int (*function_type)(int,int);

function_type getFunc()
{
   function_type test;
   test /* = ...*/;
   return test;
}

Dies kann jedoch umständlich werden, wenn es um eine große Anzahl von Funktionen geht, daher möchte ich nicht für jede (oder für jede Funktionsklasse) eine Typedef deklarieren müssen.

Ich kann die Typedef entfernen und die in der Funktion zurückgegebene lokale Variable wie folgt deklarieren:
int (*test)(int a, int b); den Funktionsrumpf so aussehen zu lassen:

{
     int (*test)(int a, int b);
     test /* = ...*/;
     return test;
}

aber dann weiß ich nicht, was ich für den Rückgabetyp der Funktion einstellen soll. Ich habe versucht:

int(*)(int,int) getFunc()
{
    int (*test)(int a, int b);
    test /* = ...*/;
    return test;
}

aber das meldet einen Syntaxfehler. Wie deklariere ich den Rückgabetyp für eine solche Funktion, ohne eine Typedef für den Funktionszeiger zu deklarieren? Ist es überhaupt möglich? Beachten Sie auch, dass ich mir bewusst bin, dass es sauberer zu sein scheint, Typedefs zu deklarieren, aber ich bin sehr darauf bedacht, meinen Code so sauber und einfach wie möglich zu strukturieren. Der Grund, warum ich die Typedefs eliminieren möchte, ist, dass sie oft nur verwendet werden, um die Abruffunktionen zu deklarieren und daher im Code redundant erscheinen.

  • +1, interessant, das habe ich mich vor einiger Zeit selbst gefragt und gerade eine typedef verwendet.

    – Dies

    16. Dezember 2013 um 17:36 Uhr

  • Sollte nicht test_type sein function_type? (Nicht, dass es so wichtig wäre, aber nur um es ganz klar zu sagen.)

    – Kninnug

    16. Dezember 2013 um 17:37 Uhr


  • In Ihrer Frage fehlen einige Dinge (z. B. was ist die Definition von test_type). Macht die Beantwortung Ihrer Frage viel schwieriger, wenn wir verwirrt sind. lol

    – Fiddle Bits

    16. Dezember 2013 um 17:37 Uhr

  • @SE Ja. Ich versuche, ein gutes Beispiel zu finden, um es als Antwort zu posten, es sei denn, Sie denken, dass dies nicht der richtige Weg ist …

    – Fiddle Bits

    16. Dezember 2013 um 17:49 Uhr

  • @AndyLin Es gibt viele. So ziemlich jedes Mal, wenn Sie einen Bibliotheks-Wrapper schreiben müssen. Um nur ein reales Beispiel aus dem Kopf zu holen, nehmen Sie an, Sie schreiben eine OpenGL-Anwendung und möchten das dynamische Laden der OpenGL-Version unterstützen, die sich auf dem System des Benutzers befindet. Dann schreiben Sie einen Wrapper um open gl und laden jede gl-Funktion, die Sie verwenden, dynamisch aus der Bibliothek. In solchen Fällen möchten Sie bei der Initialisierung jede gl-Funktion zurückgeben, indem Sie ihren Namen in dieser Version von open gl nachschlagen. Tatsächlich hat open gl Erweiterungen, die auf diese Weise geladen werden sollen

    – SE

    13. Januar 2021 um 20:55 Uhr


Benutzeravatar von Eric Postpischil
Eric Postpischil

int (*getFunc())(int, int) { … }

Damit erhalten Sie die von Ihnen angeforderte Erklärung. Wie ola1olsson feststellt, wäre es außerdem gut, es einzufügen void:

int (*getFunc(void))(int, int) { … }

Das sagt das getFunc darf keine Parameter annehmen, was helfen kann, Fehler zu vermeiden, z. B. durch versehentliches Schreiben getFunc(x, y) Anstatt von getFunc()(x, y).

  • Ich habe eine Klassenmitgliedsfunktion und möchte, dass sie einen Funktionszeiger zurückgibt. Wie kann ich es tun ? Ich kann nicht finden, wie. Ich habe es so versucht, wie Sie oben sagen, aber es hat nicht funktioniert.

    – Chaviaras michalis

    8. Dezember 2017 um 8:55 Uhr


  • Gute Antwort. Aber völlig hirntote C-Funktionszeiger-Syntax.

    – Johannes Übermann

    23. Februar 2018 um 12:11 Uhr

  • Ich würde vorschlagen, das Schlüsselwort “void” zwischen die leeren Klammern einzufügen, damit der Compiler den Fehler abfangen kann, bei dem der Aufrufer von getFunc() denken könnte, dass er / sie das Argument int,int an die eigentliche Funktion gibt und nicht an getFunc() . Das heißt, Sie möchten, dass der Compiler “getFunc (x, y)” abfängt, da der Aufrufer wahrscheinlich “getFunc () (x, y)” ausführen möchte.

    – ola1olsson

    5. März 2018 um 14:51 Uhr


  • Könnte nicht zum Thema gehören, aber es ist einfach, komplexe Funktionsdeklarationen zu evaluieren Im Uhrzeigersinn/Spiralregel

    – tonyjosi

    26. Februar 2020 um 9:46 Uhr

Benutzeravatar von yosim
Yosim

Sie können wahrscheinlich so etwas tun:

int foo (char i) {return i*2;}

int (*return_foo()) (char c)
{
   return foo;
}

aber Gott, ich hoffe, ich muss deinen Code nie debuggen …

  • Wie ich in dem Problem sagte, würde ich es nicht in einem Szenario verwenden, in dem es den Code unordentlich machte. Es ist nur für die seltenen Fälle, in denen das Deklarieren vieler Typedefs überflüssig ist

    – SE

    16. Dezember 2013 um 18:29 Uhr


  • Hoppla! Als ich das noch einmal gelesen habe, war es ein bisschen unhöflich, tut mir leid, ich habe es nicht so gemeint – es war als Witz gemeint.

    – Yosim

    16. Dezember 2013 um 19:57 Uhr

Benutzeravatar von Dmitry
Dmitri

Ich lasse dies hier, da es etwas kniffliger war als die bereits gegebenen Antworten, da es einen Funktionszeiger benötigt

(int (__cdecl *)(const char *))

und gibt einen Funktionszeiger zurück

(int (__cdecl *)(const char *))

#include <stdio.h>

int (*idputs(int (*puts)(const char *)))(const char *) {
    return puts;
}

int main(int argc, char **argv)
{
    idputs(puts)("Hey!");

    return 0;
}

Beim Umhüllen von C-Code in C++-Klassen hatte ich den gleichen Wunsch wie das ursprüngliche Poster: Einen Funktionszeiger von einer Funktion zurückgeben, ohne darauf zurückzugreifen typedefDen Funktionszeiger-Prototypen erstellen. Ich habe ein Problem mit C++ const Korrektheit, von der ich dachte, dass sie es wert ist, geteilt zu werden, auch wenn sie ein wenig vom Thema abweicht (C++), aber sie bezieht sich direkt auf die ursprüngliche Frage: die Syntax zum Zurückgeben eines C-Funktionszeigers, ohne auf a zurückzugreifen typedef.

Der folgende Code definiert eine Klasse A die einen Funktionszeiger speichert und ihn der Außenwelt durch die aussetzt get_f() Anruf. Dies ist die Funktion, die einen Funktionszeiger ohne a zurückgeben sollte typedef.

Der Punkt (der mich einige Zeit ratlos machte) war, wie man das deklariert get_f() war ein const funktionieren, dh es würde sich nicht ändern A.

Der Code enthält 2 Varianten: Die erste verwendet einen Typedef für den Funktionszeiger-Prototyp, während die zweite alles vollständig ausschreibt. Das #if wechselt zwischen den beiden.

#include <iostream>

int my_f(int i)
{
  return i + 1;
}

#if 0 // The version using a typedef'ed function pointer

typedef int (*func_t)(int);

class A
{
public:
  A(func_t f) : m_f(f) {}
  func_t get_f() const { return m_f; }

private:
  func_t m_f;
};

int main(int argc, char *argv[])
{
  const A a(my_f);
  std::cout << "result = " << a.get_f()(2) << std::endl;
}

#else // The version using explicitly prototyped function pointer    

class A
{
public:
  A(int (*f)(int)) : m_f(f) {}
  int (*get_f() const)(int) { return m_f; }

private:
  int (*m_f)(int);
};

int main(int argc, char *argv[])
{
  const A a(my_f);
  std::cout << "result = " << a.get_f()(2) << std::endl;
}

#endif

Die erwartete/gewünschte Ausgabe ist:

result = 3

Der entscheidende Punkt ist die Position des const Qualifizierer in der Zeile:

int (*get_f() const)(int) { return m_f; }

Dies ist ein dummes Beispiel, aber es ist einfach und es gibt keine Fehler. Es geht nur darum, statische Funktionen zu deklarieren:

#include <stdio.h>
#include <stdlib.h>

void * asdf(int);
static int * hjkl(char,float);

main() {
  int a = 0;
  asdf(a);
 }


void * asdf(int a) {return (void *)hjkl; }
static int * hjkl(char a, float b) {int * c; return c;}

  • Der C-Standard definiert nicht das Verhalten der Umwandlung von Zeigern auf Daten in Zeiger auf Funktionen. Dies ist auch nicht einfacher als das Beispiel des OP.

    – Andrej Mischtschenko

    16. Dezember 2013 um 17:58 Uhr

  • eigentlich wirft er keinen Zeiger auf Daten in einen Zeiger auf eine Funktion. Er hat einen Zeiger auf eine Funktion, und er wandelt ihn in eine Leerstelle* um und wandelt ihn dann wieder in eine Funktion um. dies ist gültig, und tatsächlich funktioniert die dlsym-Funktion von GNU mit void*-Rückgabetypen. Das Problem ist, dass es im Grunde eine Form von schwacher Typisierung ist, die ich zu vermeiden versuche

    – SE

    29. September 2014 um 18:29 Uhr

Benutzeravatar von Raffaele Rossi
Raffael Rossi

Ich denke du hast drei Möglichkeiten:

  1. Bleiben Sie bei typedef. Letztendlich ist es die Aufgabe von typedef.
  2. Return void* und das Casting it.
  3. Überdenken Sie Ihre Softwarearchitektur. Vielleicht können Sie uns mitteilen, was Sie zu erreichen versuchen, und sehen, ob wir Sie in eine bessere Richtung weisen können.

  • Der C-Standard definiert nicht das Verhalten der Umwandlung von Zeigern auf Daten in Zeiger auf Funktionen. Dies ist auch nicht einfacher als das Beispiel des OP.

    – Andrej Mischtschenko

    16. Dezember 2013 um 17:58 Uhr

  • eigentlich wirft er keinen Zeiger auf Daten in einen Zeiger auf eine Funktion. Er hat einen Zeiger auf eine Funktion, und er wandelt ihn in eine Leerstelle* um und wandelt ihn dann wieder in eine Funktion um. dies ist gültig, und tatsächlich funktioniert die dlsym-Funktion von GNU mit void*-Rückgabetypen. Das Problem ist, dass es im Grunde eine Form von schwacher Typisierung ist, die ich zu vermeiden versuche

    – SE

    29. September 2014 um 18:29 Uhr

Benutzeravatar von JiaHao Xu
JiaHao Xu

Sie können den folgenden Code schreiben (funktioniert nur in C++ 11 und höher):

//C++11
auto func(...) {
    int (*fptr)(...) ret = ...
    //Do sth.
    return ret;//C++11 compiler will automatically deduce the return type for you
}

Oder, wenn Sie die automatische Herleitung des Rückgabetyps nicht mögen, können Sie den Typ am Ende der Funktion angeben (wie oben, nur in C++ 11 und höher):

//C++11
auto func(...) -> int (*)(...) { /* Do sth. */ }

  • danke für die Antwort, aber die Frage bezog sich auf c, nicht auf c++.

    – SE

    9. April 2018 um 13:14 Uhr

1416610cookie-checkZurückgebender Funktionszeigertyp

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy