1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

C -> Pointer auf Funktionen

Dieses Thema im Forum "Programmieren" wurde erstellt von Vril, 18 April 2017.

  1. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123
    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. ?
     
  2. rubricanis

    rubricanis Homo ludens

    Registriert seit:
    22 August 2011
    Beiträge:
    626
    Ort:
    Ottendorf, Niederösterreich
    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
     
    Vril gefällt das.
  3. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123
    Danke für die Antwort Peter

    - das ist aber jetzt nur zur besseren Lesbarkeit auseinandergenommen ?
     
  4. rubricanis

    rubricanis Homo ludens

    Registriert seit:
    22 August 2011
    Beiträge:
    626
    Ort:
    Ottendorf, Niederösterreich
    Keine Ahnung, das ist wie ich deinen Text verstehe. Probleme lößt man am besten indem man sie in mehrere kleine auflöst und testet.Es geht bei C ja nicht um Unlesbarkeit, oder? ;)
     
  5. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123
    war es nicht mal so, dass die Korrelation zwischen C-Genialität und Sourcecode-Lesbarkeit
    indirekt proportional war? ... lach
     
  6. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123
    ...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);
     
  7. rubricanis

    rubricanis Homo ludens

    Registriert seit:
    22 August 2011
    Beiträge:
    626
    Ort:
    Ottendorf, Niederösterreich
    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 ...
     
  8. OnkelHeinz

    OnkelHeinz Member

    Registriert seit:
    25 November 2015
    Beiträge:
    56
    Ich nehme an, daß "f" steht für function, "eindimensionales Array mit Zeigern auf Funktionen füllen".
     
  9. OnkelHeinz

    OnkelHeinz Member

    Registriert seit:
    25 November 2015
    Beiträge:
    56
    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
     
  10. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123
    @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
     
  11. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123
    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: 22 April 2017 um 16:52 Uhr
  12. OnkelHeinz

    OnkelHeinz Member

    Registriert seit:
    25 November 2015
    Beiträge:
    56
    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
     
  13. Vril

    Vril Member

    Registriert seit:
    4 August 2016
    Beiträge:
    123

    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: 22 April 2017 um 23:41 Uhr