Wie übergibt man eine Funktion als Parameter in C?

Lesezeit: 7 Minuten

andrewrks Benutzeravatar
andrewrk

Ich möchte eine Funktion erstellen, die eine per Parameter übergebene Funktion für einen Datensatz ausführt. Wie übergibt man eine Funktion als Parameter in C?

  • Wenn Sie Funktionen/Arrays als Variablen verwenden, verwenden Sie IMMER typedef.

    – Muhende Ente

    13. Januar 2014 um 21:09 Uhr

  • Wir nennen es Funktionszeiger

    – AminM

    1. April 2014 um 11:11 Uhr

  • @MooingDuck Ich bin mit Ihrem Vorschlag nicht einverstanden, und Ihrem Vorschlag fehlt die Begründung, um die Schlussfolgerung zu stützen. Ich persönlich bevorzuge noch nie die Verwendung von typedef für Funktionszeiger, und ich denke, es macht den Code klarer und leichter lesbar.

    – andrewrk

    16. Dezember 2015 um 22:26 Uhr

  • @andrewrk: Du bevorzugst void funcA(void(*funcB)(int)) und void (*funcA())() zu typedef void funcB(); void funcA(funcB) und funcB funcA()? Ich sehe den Vorteil nicht.

    – Muhende Ente

    16. Dezember 2015 um 23:27 Uhr


  • Siehe die Standardbibliotheksfunktionen qsort und bsearch für Beispiele, wie dies gemacht wird.

    – Bob Jarvis – Слава Україні

    15. Februar 2021 um 12:45 Uhr

Benutzeravatar von Niyaz
Niyaz

Erklärung

Ein Prototyp für eine Funktion, die einen Funktionsparameter übernimmt, sieht wie folgt aus:

void func ( void (*f)(int) );

Diese besagt, dass der Parameter f wird ein Zeiger auf eine Funktion sein, die a hat void Rückgabetyp und die eine einzelne nimmt int Parameter. Die folgende Funktion (print) ist ein Beispiel für eine Funktion, an die übergeben werden könnte func als Parameter, weil es der richtige Typ ist:

void print ( int x ) {
  printf("%d\n", x);
}

Funktionsaufruf

Beim Aufruf einer Funktion mit einem Funktionsparameter muss der übergebene Wert ein Zeiger auf eine Funktion sein. Verwenden Sie dazu den Namen der Funktion (ohne Klammern):

func(print);

würde nennen funcund übergibt ihm die Druckfunktion.

Funktionskörper

Wie bei jedem Parameter, func kann nun den Namen des Parameters im Funktionsrumpf verwenden, um auf den Wert des Parameters zuzugreifen. Sagen wir das func wendet die übergebene Funktion auf die Zahlen 0-4 an. Überlegen Sie sich zunächst, wie die Schleife aussehen würde, um print direkt aufzurufen:

for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
  print(ctr);
}

Seit funcDas sagt die Parameterdeklaration von f der Name für einen Zeiger auf die gewünschte Funktion ist, erinnern wir uns zunächst daran, dass if f ist dann ein Zeiger *f ist das Ding f zeigt auf (dh die Funktion print in diesem Fall). Ersetzen Sie daher einfach jedes Vorkommen von print in der obigen Schleife durch *f:

void func ( void (*f)(int) ) {
  for ( int ctr = 0 ; ctr < 5 ; ctr++ ) {
    (*f)(ctr);
  }
}

Quelle

  • In Ihrem ersten und letzten Codebeispiel ist das * nicht obligatorisch. Sowohl die Funktionsparameterdefinition als auch die f Funktionsaufruf annehmen kann f genauso wie ohne *. Es könnte jedoch eine gute Idee sein, es so zu machen, wie Sie es tun, um deutlich zu machen, dass Parameter f ein Funktionszeiger ist. Aber es schadet oft der Lesbarkeit.

    – Gauthier

    22. Februar 2012 um 12:52 Uhr


  • Sehen [c99, 6.9.1§14] zum Beispiel. Beides ist natürlich richtig, ich wollte nur die Alternative erwähnen.

    – Gauthier

    22. Februar 2012 um 12:58 Uhr

  • Wirklich? Die am besten bewertete Antwort enthält keinen einzigen Hinweis auf die Verwendung von a typedef für Funktionszeiger? Entschuldigung, muss abstimmen.

    – Jonathon Reinhart

    1. Oktober 2014 um 8:03 Uhr

  • @ JonathonReinhart, was wären Vorteile mit dem ‘typedef’-Ansatz? Diese Version sieht jedoch viel sauberer aus und es fehlen auch zusätzliche Anweisungen. ziemlich viel Starter hier.

    – Abhinav Gauniyal

    22. Februar 2015 um 7:04 Uhr

  • @JonathonReinhart gut gesehen; Es sollte ausdrücklich darauf hingewiesen werden, dass Pointer Typedefs den Code verschleiern und daher nicht verwendet werden sollten.

    – MM

    24. November 2015 um 2:39 Uhr

Benutzeravatar von roo
Zimmer

Diese Frage hat bereits die Antwort für das Definieren von Funktionszeigern, aber sie können sehr chaotisch werden, besonders wenn Sie sie in Ihrer Anwendung herumreichen. Um diese Unannehmlichkeiten zu vermeiden, würde ich empfehlen, dass Sie den Funktionszeiger in etwas Lesbareres schreiben. Zum Beispiel.

typedef void (*functiontype)();

Deklariert eine Funktion, die void zurückgibt und keine Argumente akzeptiert. Um einen Funktionszeiger auf diesen Typ zu erstellen, können Sie jetzt Folgendes tun:

void dosomething() { }

functiontype func = &dosomething;
func();

Für eine Funktion, die ein int zurückgibt und ein char akzeptiert, würden Sie dies tun

typedef int (*functiontype2)(char);

und es zu benutzen

int dosomethingwithchar(char a) { return 1; }

functiontype2 func2 = &dosomethingwithchar
int result = func2('a');

Es gibt Bibliotheken, die dabei helfen können, Funktionszeiger in gut lesbare Typen umzuwandeln. Das Boost-Funktion Die Bibliothek ist großartig und die Mühe wert!

boost::function<int (char a)> functiontype2;

ist so viel schöner als die oben.

  • Wenn Sie einen Funktionszeiger in einen Typ umwandeln möchten, benötigen Sie die Boost-Bibliothek nicht. Benutz einfach typedef; es ist einfacher und erfordert keine zusätzlichen Bibliotheken.

    – wizzwizz4

    9. April 2016 um 11:50 Uhr

  • Ist die Boost-Bibliothek nicht C++? Warum erwähnen Sie es in einer C-Frage?

    – 12431234123412341234123

    2. Oktober 2020 um 12:48 Uhr

  • Platzieren Sie für Funktionen, die eine andere Aufrufkonvention verwenden, die Aufrufkonvention vor dem ersten *. So was: typedef void(__stdcall* funcPtr)(int arg1, int arg2);

    – Dwedit

    19. September 2021 um 18:04 Uhr

Richards Benutzeravatar
Richard

Seit C++11 können Sie die funktionale Bibliothek um dies kurz und generisch zu tun. Die Syntax ist zB

std::function<bool (int)>

wo bool ist hier der Rückgabetyp einer Funktion mit einem Argument, deren erstes Argument vom Typ ist int.

Ich habe unten ein Beispielprogramm eingefügt:

// g++ test.cpp --std=c++11
#include <functional>

double Combiner(double a, double b, std::function<double (double,double)> func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

Manchmal ist es jedoch bequemer, eine Vorlagenfunktion zu verwenden:

// g++ test.cpp --std=c++11

template<class T>
double Combiner(double a, double b, T func){
  return func(a,b);
}

double Add(double a, double b){
  return a+b;
}

double Mult(double a, double b){
  return a*b;
}

int main(){
  Combiner(12,13,Add);
  Combiner(12,13,Mult);
}

  • Die Frage betrifft C; C++ kommt hier nicht zum Einsatz.

    – Superkat

    29. Oktober 2015 um 23:44 Uhr

  • Auf die Frage für C ++ (stackoverflow.com/questions/6339970/…) wird hier verwiesen, daher denke ich, dass diese Antwort vorhanden ist.

    – mr_T

    24. März 2016 um 11:00 Uhr

  • Vielleicht sollte die Frage für C++ hier nicht erwähnt werden, weil diese Frage für C ist.

    – Michael Fulton

    19. April 2018 um 16:22 Uhr

  • Diese Frage tauchte zuerst auf, als ich nach “C++-Funktionsaufruf als Parameter” suchte, also erfüllt diese Antwort hier trotzdem ihren Zweck.

    – ufoxDan

    7. November 2019 um 21:50 Uhr

Benutzeravatar von Yogeesh HT
Yogeesh HT

Passieren Adresse einer Funktion als Parameter für eine andere Funktion Wie nachfolgend dargestellt

#include <stdio.h>

void print();
void execute(void());

int main()
{
    execute(print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void f()) // receive address of print
{
    f();
}

Wir können die Funktion auch als Parameter mit übergeben Funktionszeiger

#include <stdio.h>

void print();
void execute(void (*f)());

int main()
{
    execute(&print); // sends address of print
    return 0;
}

void print()
{
    printf("Hello!");
}

void execute(void (*f)()) // receive address of print
{
    f();
}

Benutzeravatar von doppelheathen
Doppelheide

Funktionen können als Funktionszeiger “übergeben” werden, gemäß ISO C11 6.7.6.3p8: “Eine Deklaration eines Parameters als „Funktionsrückgabetyp“ soll angepasst werden an „Zeiger auf Funktionsrückgabetyp“, wie in 6.3.2.1. “. Zum Beispiel dies:

void foo(int bar(int, int));

ist äquivalent dazu:

void foo(int (*bar)(int, int));

  • Aus welchem ​​Dokument zitierst du? Irgendein Link dazu?

    – Rafael Eyng

    29. Januar 2020 um 21:41 Uhr

  • Ich zitiere aus dem ISO C11-Standard.

    – Doppelheide

    5. Februar 2020 um 12:57 Uhr

Ich werde es mit einem einfachen Beispielcode erklären, der a dauert compare fungieren als Parameter für einen anderen sorting Funktion. Nehmen wir an, ich habe eine Bubble-Sort-Funktion, die eine benutzerdefinierte Vergleichsfunktion verwendet und sie anstelle einer festen if-Anweisung verwendet.

Vergleichsfunktion

bool compare(int a, int b) {
    return a > b;
}

Jetzt die Bubble-Sortierung, die eine andere Funktion als Parameter zum Durchführen des Vergleichs verwendet

Bubble-Sort-Funktion

void bubble_sort(int arr[], int n, bool (&cmp)(int a, int b)) {

    for (int i = 0;i < n - 1;i++) {
        for (int j = 0;j < (n - 1 - i);j++) {
            
            if (cmp(arr[j], arr[j + 1])) {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

Endlich, das main die die Bubblesort-Funktion aufruft, indem sie die boolesche Vergleichsfunktion als Argument übergibt.

int main()
{
    int i, n = 10, key = 11;
    int arr[10] = { 20, 22, 18, 8, 12, 3, 6, 12, 11, 15 };

    bubble_sort(arr, n, compare);
    cout<<"Sorted Order"<<endl;
    for (int i = 0;i < n;i++) {
        cout << arr[i] << " ";
    }
}

Ausgabe:

Sorted Order
3 6 8 11 12 12 15 18 20 22

  • Aus welchem ​​Dokument zitierst du? Irgendein Link dazu?

    – Rafael Eyng

    29. Januar 2020 um 21:41 Uhr

  • Ich zitiere aus dem ISO C11-Standard.

    – Doppelheide

    5. Februar 2020 um 12:57 Uhr

Benutzeravatar von saint_groceon
saint_groceon

Sie müssen a bestehen Funktionszeiger. Die Syntax ist ein wenig umständlich, aber sie ist wirklich mächtig, sobald Sie sich damit vertraut gemacht haben.

1428390cookie-checkWie übergibt man eine Funktion als Parameter in C?

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

Privacy policy