Wozu dienen Funktionszeiger? [duplicate]

Lesezeit: 5 Minuten

Benutzer-Avatar
haris

Mögliches Duplikat:

Was ist der Sinn von Funktionszeigern?

Ich versuche zu verstehen, wo in den praktischen Szenarien Funktionszeiger verwendet werden. und kann mir bitte jemand ein praktisches Beispiel geben, wo wir die Funktion selbst als Argument an eine andere Funktion übergeben müssen.

  • Dies ist C#, geht aber auch auf C/C++ und die Praktikabilität von Funktionszeigern ein: stackoverflow.com/questions/667410/…

    – Algorithmus

    23. Januar 2012 um 16:48 Uhr

Benutzer-Avatar
Toni der Löwe

Funktionszeiger können beim Erstellen nützlich sein Callback-Mechanismusund müssen die Adresse einer Funktion an eine andere Funktion übergeben.

Sie können auch nützlich sein, wenn Sie ein Array von Funktionen speichern möchten, um sie beispielsweise dynamisch aufzurufen.

Callback-Routinen scheinen das bisher häufigste Szenario zu sein. Es gibt jedoch noch viele andere …

Endliche Zustandsmaschinen wobei die Elemente von (mehrdimensionalen) Arrays die Routine angeben, die den nächsten Zustand verarbeitet/handhabt. Dadurch bleibt die Definition des FSM an einem Ort (dem Array).

Funktionen aktivieren und das Deaktivieren von Funktionen kann unter Verwendung von Funktionszeigern erfolgen. Möglicherweise haben Sie Funktionen, die Sie aktivieren oder deaktivieren möchten, die ähnliche, aber unterschiedliche Dinge tun. Anstatt Ihren Code mit if-else-Konstrukten zum Testen von Variablen zu füllen und zu überladen, können Sie ihn so codieren, dass er einen Funktionszeiger verwendet, und dann können Sie Funktionen aktivieren/deaktivieren, indem Sie den Funktionszeiger ändern/zuordnen. Wenn Sie neue Varianten hinzufügen, müssen Sie nicht alle Ihre if-else- oder Fallwechsel-Fälle aufspüren (und riskieren, eine zu verpassen); Stattdessen aktualisieren Sie einfach Ihren Funktionszeiger, um die neue Funktion zu aktivieren oder die alte zu deaktivieren.

Reduzierung von Code-Unordnung Ich habe dies im vorherigen Beispiel angesprochen. Beispiele wie …

switch (a) {
case 0:
    func0();
    break;
case 1:
    func1();
    break;
case 2:
    func2();
    break;
case 3:
    func3();
    break;
default:
    funcX();
    break;
}

Kann vereinfacht werden zu …

/* This declaration may be off a little, but I am after the essence of the idea */
void (*funcArray)(void)[] = {func0, func1, func2, func3, funcX};
... appropriate bounds checking on 'a' ...
funcArray[a]();

Es gibt viele mehr. Hoffe das hilft.

  • FWIW sollte die Deklaration sein void (*funcArray[])(void) = {func0, func1, func2...}; (funcArray ist ein Array von Zeigern auf Funktionen…). Denken Sie daran, dass die Deklaration die Verwendung nachahmt; wenn der Ausdruck im Code ist funcArray[a]()dann wird die Deklaration genauso aufgebaut.

    – Johannes Bode

    23. Januar 2012 um 18:28 Uhr

  • @JohnBode – Sehr geschätzt. Obwohl ich seit über 20 Jahren mit C arbeite, komme ich immer noch mit der Funktionszeiger-Syntax durcheinander. Normalerweise entscheide ich mich für den einfacheren (für mich) Weg, zuerst den Funktionszeiger zu typisieren und dann ein Array der typdefinierten Variablen zu deklarieren.

    – Funkelnd

    23. Januar 2012 um 18:54 Uhr

  • @Sparky Vereinbart bezüglich der Typedef. Es macht Situationen wie Arrays von Funktionszeigern oder Zeiger auf Funktionszeiger viel einfacher lesbar.

    – Brian McFarland

    23. Januar 2012 um 22:50 Uhr

  • @Sparky: Ich muss den Typedefs widersprechen; für mich verdunkeln sie ebenso wie sie erhellen. Wenn ich einen etwas hässlichen Typ mag int *(*(*f)[N])(void)Ich weiß sofort, dass Ausdrücke mit f aussehen x = *(*(*f)[i])(); – Ich muss nicht nach einer Reihe von Typedefs suchen und daraus den Ausdruck rekonstruieren.

    – Johannes Bode

    25. Januar 2012 um 11:52 Uhr

Benutzer-Avatar
Taskinoor

Eine häufige Verwendung ist die Implementierung von a Callback-Funktion.

Versuchen Sie, etwas zu sortieren, indem Sie verwenden qsort Bibliotheksfunktion. Der letzte Parameter ist ein Zeiger auf die von Ihnen geschriebene Komparatorfunktion.

Das erste, was mir als sehr nützliche Anwendung in den Sinn kommt, ist eine Schaltfläche. Nehmen Sie den folgenden Code:

int buttonID = CreateButton ("Click Me!", 100, 100, 200, 100, onClick);

Dies würde eine Schaltfläche bei (100,100) mit einer Breite von 200 und einer Höhe von 100 erstellen. Jedes Mal, wenn Sie darauf klicken, wird onClick aufgerufen.

Ich verwende etwas Ähnliches in einem persönlichen Windows-API-Wrapper. Es macht das Erstellen von Schaltflächen usw. so viel einfacher.

Es gibt zwei Hauptverwendungen für Funktionszeiger:

  • Rückrufe – verwendet für Event-Handler, Parser-Spezialisierung, Komparatorfunktionsübergabe …
  • Plugins und Erweiterungen – Die Zeiger auf Funktionen, die von Plugins oder Bibliothekserweiterungen bereitgestellt werden, werden von einer Standardfunktion gesammelt GetProcAddress, dlsym oder ähnliches, die den Funktionsbezeichner als Namen nehmen und einen Funktionszeiger zurückgeben. Absolut lebenswichtig für APIs wie OpenGL.

Benutzer-Avatar
BRPocock

Nun, die Antwort Nr. 1 lautet: qsort. Die Komparatorroutine, die qsort wird als Funktionszeiger übergeben. Viele andere „generische Algorithmus“-Funktionen verwenden Komparatoren auf ähnliche Weise; zB könnte eine Hashtable-Implementierung Ihre Hash-Funktion akzeptieren.

GUI-Toolkits und Anwendungs-Frameworks in C-Sprache (z. B. Gnome/Gtk+/Glib) akzeptieren häufig Funktionszeiger als „Rückrufe“ für Timer- oder Benutzeroberflächenereignisse. (ZB: „rufe diese Funktion immer dann auf, wenn auf diese Schaltfläche geklickt wird“ oder „… wann immer dieser Timer abläuft“)

Tatsächlich akzeptiert der meiste „OOP-ähnliche“ oder „ereignisgesteuerte“ Code in C Funktionszeiger aus einem ähnlichen Grund.

Benutzer-Avatar
Frxstrom

Sie können es verwenden, um einen Rückruf an eine Funktion zu übergeben. Beispielsweise möchten Sie möglicherweise ein Array mit sortieren qsort(). Diese Funktion nimmt eine Vergleichsfunktion als eines ihrer Argumente, was bedeutet, dass Sie Ihre eigenen Sortierreihenfolgen verwenden können:

// All odd numbers are before even numbers
int cmpoddeven(const void *xp, const void *yp) {
  int x = *((int*) xp);
  int y = *((int*) yp);
  if(x == y)
    return 0;
  if(x % 2 == y % 2) {
    return (x < y ? -1 : 1);
  if(x % 2 == 1)
    return -1;
  return 1;
}

int main() {
   int array[] = {1, 2, 3, 4, 5};
   // calling qsort with cmpoddeven as the comparison function
   qsort(array, 5, sizeof(int), &cmpoddeven);
   // array == {1, 3, 5, 2, 4};
}

  • Eine übliche Verwendung von Funktionszeigern in C findet sich in eingebetteter Software zur Behandlung von Interrupts. Der Interrupt-Handler muss für jeden gegebenen Interrupt eine bestimmte Funktion aufrufen. Dies beinhaltet das Programmieren des Interrupt-Controllers mit der Adresse dieser Funktion.

    – Phil

    13. Juni 2019 um 2:58 Uhr

1383880cookie-checkWozu dienen Funktionszeiger? [duplicate]

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

Privacy policy