C -> Pointer auf Funktionen

Vril

Well-Known Member
ich hab da mal ne Frage an die C Spezialisten:

Ich will statt wirrer if oder Switch Schachtelungen ein eindimensionales Array mit Zeigern auf Funktionen füllen , da ich deren Reihenfolge und Häufigkeit des Aufrufs erst im Programmlauf ermitteln kann - und dieses Array dann sequentiell abarbeiten lassen ....

Ich muss also eine Funktion f_run deklarieren, welche ein Argument x vom Typ unsigned long und eine Variable Anzahl Char erwartet und selbst einen Funktionspointer zurückgibt, welcher auf eine weitere Funktion zeigt, die als Argument ebenfalls einen unsigned Long und eine unbekannte Anzahl Char verlangt und einen Zeiger auf Char zurückgibt:
Code:
char* (*f_run(unsigned Long x, ...))(unsigned long, ...)

Wäre das so o.k. ?
 
Hmmm, deine Beschreibung ist etwas konfus. Wenn ich dich recht verstehe würde ich das in 2 typedefs auflösen,etwa so:
Code:
typedef char* (*f_get)(unsigned long, ...);
typedef f_get (*f_run)(unsigned long, ...);

HTH, Peter
 
Danke für die Antwort Peter

- das ist aber jetzt nur zur besseren Lesbarkeit auseinandergenommen ?
 
...ich werde es übrigens so lösen, dass ich auf die Funktion die eine FunktionAdresse zurückgeben sollte ganz verzichtete
indem ich das Array mit den Funktionszeigern direkt fülle...
also im Prinzip so:

Code:
typedef char*(*f_run)(unsigned long x, ...)
f_run (*f_run_array[5](unsigned long,...)={NULL};
.
.
.
f_run_array[0]=&f1(unsigned long x = 7);
f_run_array[1]=&f2(unsigned long x = 0);
f_run_array[2]=&f4(unsigned long x = 8);
f_run_array[3]=&f3(unsigned long x = 4);
f_run_array[4]=&f1(unsigned long x = 9);
 
Du solltest dir angewöhnen verständlichen Code (wenn auch minimal) anzugeben den man verstehen kann. Was ist hier z.B. f1...?

Aber egal: Hauptsache es läuft ...
 
. . . ein eindimensionales Array mit Zeigern auf Funktionen . . .
Wenn ich das richtig verstanden habe, dann meinst Du so etwas in der Art:

Code:
//Zeigerfeld - eindimensionales Array mit Zeigern auf Funktionen füllen, 19. April 2017

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

#define MAX 10

int main(void)
{
    int *zeigerfeld[10];
    int func[10];
    int i, j;
   
    for(i = 1, j = 2; i <= MAX; i++, j += 2)
    {
        //Ohne Typumwandlung Warnung unter Windows
        zeigerfeld[i] = (int*)func[j];
        printf("\nFunktion[%3d] hat den Wert: %3d\n", i, j);
    }
    return(0);
}

Beispiel:
Zeigerfeld2017-04-19_192500.jpg
 
@OnkelHeinz

Nein, so ganz triffst Du mein Ansinnen nicht...
Da der Faden jetzt schon etwas durcheinander geht, will ich es nochmal ordnen:

Nehmen wir an, ich brauche zur Loesung eines Problemes 5 verschiedene Funktionen,
die logischerweise ganz unterschiedliche Dinge tun und die ganz simpel nacheinander aufgerufen werden muessen!
(1)Allerdings ergibt sich waehrend der Programmausfuehrung erst, in welcher Reihenfolge und wie oft sie aufgerufen werden
muessen.
(2)Desweiteren duerfen diese Funktionen aber erst sequentiell aufgerufen werden und abarbeiten, wenn die unter (1)
genannte Kriterien erfuellt bzw. bekannt sind

D.h. ist brauche irgendwie 2 Programmzweige die ich jetzt mal schlicht Analyse und Arbeit nenne.

es sollte also eine Funktion Analyse f_analyse() geben und 5 Funktionen f_work1() bis f_work5()

die f_Analyse() sollte so oft aufgerufen werden, wie eine der f_work1() bis f_work5() notwendig sind -
ohne das dabei jedoch die f_work() Funktionen selbst aufgerufen werden, die duerfen zu diesem Zeitpunkt ja
noch nicht arbeiten.

Also sollte die f_Analyse() bei jedem Aufruf nur den entsprechenden Funktionszeiger von f_work1() oder f_work(2) usw. zurueckgeben
und diesen Pointer in ein dynamisches Funktionszeiger-Array schieben.
D.h bei jeden N-ten Aufruf von f_Analyse() waere der Rueckgabewert die Adresse einer der an dieser Stelle ereforderlichen
f_work(x) Funktion der dann in das FunktionszeigerArray[N] geschoben wird.

Nach Beendigung des Analyse-Teils kann dann irgendwann der Arbeitszweig gestartet werden,
indem einfach in einer Schleife das FunktionszeigerArray vom Index 0 bis N durchlaufen wird
und in jedem Step zur enstprechenden Funktionsadresse gesprungen wird.

Also das ist jetzt die Skizze meines urspruenglichen Ansinnens...

@rubricanis

sorry Peter - fuer die schnoddrigen Code-Beispiele,
die waren ja stark abstrahiert - weil ich den Originalcode sicher um die Ohren gehauen bekommen haette

denn wenn man z.B. etwas in ein Array schreibt und die Stelle, also den entsprechende Index
mit dem Rueckgabewert von printf bestimmt (anzahl der ausgegebenen zeichen ohne terminator) -
weil es da grade so gut passt... und weil es ja auch erstmal witzig ist .... lach

o.k. auf jeden Fall - Vielen Dank an Euch
walter
 
so .. ich hab versucht das Thema nochmal zusammenzufassen:

Code:
#include <stdio.h>

// Hier wird eine Zeiger auf ein Funktion deklariert,
// die 2 int Argumente erwartet und einen long-Wert zurueckgibt
// also:
// - fctPointer ist hier der deklarierte Zeiger auf eine Funktion *fctPointer
long (*fctPointer)(int, int);

// die auf den ersten Blick kryptische Schreibweise mit den Klammern
// ist letztendlich ganz logisch, denn ohne Klammern erhielte man einen
// ganz andere Aussage - naemlich eine Funktion die natuerlich wieder 2 int
// als Parameter erhaelt - aber einen long Zeiger zurueckgeben will
// also etwas ganz anderes, wie das folgende Beispiel zeigt
long *fct(int,int);

// Eine gute Idee ist mit typedef einen passenden Datentyp fuer die Funktionszeiger
// anzulegen, die wuerde fuer unser Beispiel z.B. so aussehen:
typedef long (*fctPointerTyp) (int, int);

// fctPointerTyp ist jetzt also der Datentyp:
// Zeiger auf Funktion die 2 integer will und long zurueckgibt
//
// will man z.B. die Zeiger von verschiedenen Funktionen ( eines Typs ! )
// in ein Array speichern, genuegt es ja nicht ein einfaches PointerArray zu
// deklarieren - denn wie will man dann beim Aufruf die Argumente uebergeben?
// Deshalb macht der mit typedef definierte Datentyp hier besonders Sinn:
// ich deklariere und initialisiere es hier mal mit den nachfolgenden
// BeispielFunktionen:
long summe(int ix, int iy) { return (long) ix+iy; }
long produkt(int ix, int iy) { return (long) ix*iy; }
long modulo(int ix, int iy) { return (long) ix%iy; }

// jetzt die Adressen ins FunktionsPointerArray
fctPointerTyp fctArray[3] = {summe, produkt, modulo};

// will man Funktionen als Parameter an Funktionen uebergeben sind
// sind Funktionszeiger zwingend erforderlich            */
// die Parameter sind also 2 long functions, die jeweils 2 int Parameter brauchen und 2 Integer,
// mit denen die Parameterfunktionen "gefuettert" werden
int rechne(long (*fs)(int, int),long (*fm)(int, int), int a, int b)
{
    return (int) (fs(a,b) * fm(a,b));
}

int main(void)
{
    int ix = 13;
    int iy = 5;

    printf("Funktion summe()     -   Rueckgabewert: %ld\n", summe(ix,iy));

    fctPointer = &summe;    // Adresse von Summe an den Pointer            
    printf("fctPointer = &summe  -   Rueckgabewert: %ld\n", fctPointer(ix,iy));

    fctPointer = summe;    // man kann das & auch weglassen
    printf("fctPointer = summe   -   Rueckgabewert: %ld\n", fctPointer(ix,iy));

    fctPointer = produkt;
    printf("fctPointer = produkt -   Rueckgabewert: %ld\n", fctPointer(ix,iy));

    /* jetzt benutzen wir mal das Array fuer Funktionszeiger */
    printf("fctArray[0] -   Rueckgabewert: %ld\n", fctArray[0](ix,iy));
    printf("fctArray[1] -   Rueckgabewert: %ld\n", fctArray[1](ix,iy));
    printf("fctArray[2] -   Rueckgabewert: %ld\n", fctArray[2](ix,iy));

    // jetzt mal Funktionspointer an eine Funktion uebergeben
    // zuvor mal die Zeiger an neue Variablen zu uebergeben
    fctPointerTyp f1 = fctArray[0];
    fctPointerTyp f2 = fctArray[2];
    // summe, modulo und die beiden int an rechne uebergeben und rueckgabe der funktion ausgeben
    // vorher jedoch mal nen Zeiger auf printf setzten
    int (*schreibe)(const char*, ...) = printf;
    // schreibe zeigt auf printf, f1 zeigt auf summe, f2 zeigt auf modulo
    schreibe("rechne - Rueckgabewert: %d\n", rechne(f1,f2,ix,iy));

    // mann kann somit natuerlich auch wunderbaren Unfug machen
    char __[] = "Das ist Unfug!!!\n";
    int (*_)(const char*, ...)=printf;
    _(__);
}
 
Zuletzt bearbeitet:
// will man Funktionen als Parameter an Funktionen uebergeben sind
// sind Funktionszeiger zwingend erforderlich

Nicht immer! Man kann auch einfach Funktionen als Parameter übergeben, ohne Zeiger.

Code:
//Funktionen an Funktionen als Parameter, 22. April 2017

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

//Funktionsdeklarationen
int funca(int);
int funcb(int);
int funcsumme(int, int);

int main(void)
{
    int i, j;
    printf("\nGeben Sie zwei Zahlen ein, ich addiere sie.\n");
    printf("Zahl 1: "); scanf("%d", &i);
    printf("Zahl 2: "); scanf("%d", &j);
   
    printf("\nDie Summe ist: %4d", funcsumme(funca(i), funcb(j)));
   
    return(0);
}

//Funktionsdefinitionen
int funca(int i)
{
    return( i );
}

int funcb(int j)
{
    return( j );
}

int funcsumme(int a, int b)
{
    int summe;
    return(summe = a + b);
}

Beispiel:
Funktionsparameter.jpg
 
Nicht immer! Man kann auch einfach Funktionen als Parameter übergeben, ohne Zeiger.


printf erwartet in Deinem Beispiel -aufgrund des Formatbezeichners '%4d' einen Integer-Wert.
und diesen Integer-Wert gibt Deine function funcsumme zurueck, genauso wie funcsumme als
Parameter keine Funktionen sondern 2 Integer will und bekommt.
Das ist ja alles voellig korrekt!

Mit anderen Worten:
Ich sehe in deinem Beispiel nirgends eine Funktion, der als Parameter
Funktionen uebergeben werden sollen, sondern vielmehr ist
Code:
printf("\nDie Summe ist: %4d", funcsumme(funca(i), funcb(j)));
nur eine vereinfachte Schreibweise fuer:

Code:
int erg, a, b;
a = funca(i);
b = funcb(i);
erg = funcsumme(a, b);
printf("\nDie Summe ist: %4d", erg);
 
Zuletzt bearbeitet:
Zurück
Oben