C: Wie kann ich ein einzelnes Funktionszeigerarray für Funktionen mit variabler Parameteranzahl verwenden?

Lesezeit: 3 Minuten

Die Frage sagt eigentlich schon alles.

Ich bin mir nicht sicher, wie das geht, und bin noch nicht in die Nähe von irgendetwas gekommen, das funktioniert.

Hier sind einige Beispielfunktionen:

add(int x, int y) {
  return x+y;
}

und,

mean(int x1, int y1, int x2, int y2) {
  return (x1 + y1 + x2 + y2) / 4;
}

Bisher habe ich versucht, typedef mit beiden zu verwenden, aber ich kann nicht herausfinden, wie ich etwas auf einen der beiden Typen verweisen kann:

typedef int (*mathfunc2)(int x, int y);
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2);

????? func_table[2] = {add, mean};

Sie müssen einen Funktionszeigertyp auswählen, der als “generischer Funktionszeiger” verwendet werden soll, diesen Typ verwenden, um Ihr Array zu definieren, und explizite Umwandlungen verwenden. Durch das Umwandeln eines Funktionszeigertyps in einen anderen und dann wieder zurück wird der Wert garantiert erhalten.

Mit anderen Worten:

typedef int (*generic_fp)(void);

generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean };

Dann anrufen addmüssen Sie es wieder in den richtigen Typ umwandeln:

result = ((mathfunc2)func_table[0])(x, y);

Sie können einige Makros definieren, wenn Sie es schmackhafter finden:

#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2)
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4)

result = FUNC_2(func_table[0], x, y);

  • Genau das hat gewirkt! Tausend Dank, Sir. Ich werde mich hoffentlich daran erinnern, wenn ich jemals 15 Ruf bekomme und dir einen Pfeil nach oben gebe 🙂

    – vaughanj

    6. Oktober 2011 um 6:24 Uhr

  • Ich hatte den Eindruck, dass sich Funktionszeiger aufgrund der Parameter anders verhalten als normale void-Zeiger. Dass Sie Funktionszeiger nicht mit unterschiedlichen Parametern mischen könnten, da der Stapel beim Aufräumen beschädigt werden würde. Habe ich etwas falsch verstanden?

    – Ian

    6. Oktober 2011 um 12:23 Uhr

  • @Ioan: Sie müssen die Funktion über einen Zeiger aufrufen, der mit dem deklarierten Typ der Funktion kompatibel ist. Wenn Sie also den Funktionszeiger zur Speicherung in einen anderen Typ umwandeln, müssen Sie ihn zum Aufrufen wieder in den richtigen Typ umwandeln Funktion. Das Beispiel in dieser Antwort tut dies.

    – Café

    6. Oktober 2011 um 12:55 Uhr

  • Ah ich sehe. Gut zu wissen, dass es auf den Anruf ankommt, nicht auf die Speicherung. Danke.

    – Ian

    6. Oktober 2011 um 17:52 Uhr

Du könntest die verwenden Fassadenmuster so was:

int add(int x, int y);
int mean(int x1, int y1, int x2, int y2);

typedef int (*operation_fp)(int argc, int* argv);

int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); }
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); }

operation_fp func_table[2] = { add_wrapper, mean_wrapper };

Obwohl der Code hässlich ist, erfüllt er seinen Zweck. Sie sollten den Wrappern etwas Validierungslogik hinzufügen.

  • Was ist mit Funktionen, die verschiedene Arten von Argumenten annehmen? int f1(int x); int f2(Zeichen x);

    – Dok

    23. Dezember 2021 um 11:47 Uhr

Benutzeravatar von BLUEPIXY
BLUEPIXY

int (*func[])() = { add, mean };

  • Funktionszeiger vom Typ int (*)(int, int) und int (*)(int, int, int, int) sind nicht kompatibel mit Funktionszeigern des Typs int (*)(int, ...).

    – Café

    6. Oktober 2011 um 8:52 Uhr

Diese beiden Funktionstypen sind nicht kompatibel. Genau genommen könnten sie mit ganz anderen Argumentübergaben implementiert werden. Eine Implementierung könnte beispielsweise wählen, dass alle Funktionen mit bis zu 3 Parametern diese über Register erhalten und alle anderen Funktionen sie über den Stack erhalten.

Was Sie jedoch tun können, ist, beide Funktionen mit zu definieren Varargs Parameter, damit sie demselben Parameterübergabeschema folgen.

Wie wollten Sie diese Funktionen überhaupt aufrufen, ohne zu wissen, wie viele Parameter sie erwarten?

1437560cookie-checkC: Wie kann ich ein einzelnes Funktionszeigerarray für Funktionen mit variabler Parameteranzahl verwenden?

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

Privacy policy