Funktionsaufruf



  • Ich habe ein Funktion aus einer Library:

    func(Mat A, int row, int* ncols, const int (*cols)[], const double (*vals)[]);
    

    habe dann versucht diese aufzurufen. Bis ich dann die Lösung gefunden habe:

    int row;
    int cols;
    const int    *cols;
    const double *vals;
    
    func(A,row,&ncols,&cols,&vals);
    

    mir ist aber eigentlich nicht so Recht klar warum! Könnte das jemand kommentieren?

    Wenn ich eine eigene Funktion schreibe:

    void func2(double (*a)[])
    {
     //...
    }
    

    und mit:

    double *g;
    func2(&g);
    

    aufrufe, dann schmeisst der Compiler eine Fehlermeldung?!



  • Was für eine Fehlermeldung schmeißt denn der Compiler?

    (btw, was macht denn die Funktion? Die Parameterliste sieht so aus, als ob sie ein Array von Zeigern erwartet und keinen einzelnen Zeiger)



  • NoPanic2007 schrieb:

    ...
    Wenn ich eine eigene Funktion schreibe:

    void func2(double (*a)[])
    {
     //...
    }
    

    und mit:

    double *g;
    func2(&g);
    

    aufrufe, dann schmeisst der Compiler eine Fehlermeldung?!

    Klar. Was hättest Du denn erwartet ? 😕
    Wie CStoll schon schrieb:

    CStoll schrieb:

    ...Die Parameterliste sieht so aus, als ob sie ein Array von Zeigern erwartet und keinen einzelnen Zeiger)

    Wenn Du eine Funktion geschrieben hättest

    void func2(string)
    {
     //...
    }
    

    und mit:

    double g
    func2(g);
    

    gefüllt hättest, hättest Du ja auch zurecht einen Compilerfehler bekommen.

    Ein "Zeiger auf double" ist halt nicht dasselbe wie ein "Array von Zeigern auf double"....

    Gruß,

    Simon2.



  • aber das ist doch kein Array von Zeigern:

    const int    *cols;
    const double *vals;
    

    und der aufruf funktioniert ja:

    func(A,row,&ncols,&cols,&vals);
    

    😕



  • Da kann's sein, daß der Compiler bei const-Parametern ein wenig toleranter ist.

    (ansonsten wäre es immer noch hilfreich zu wissen, welche Fehlermeldung du bekommen hast)



  • NoPanic2007 schrieb:

    aber das ist doch kein Array von Zeigern...

    Also das hier schon:

    NoPanic2007 schrieb:

    ...

    void func2(double (*a)[])
    ...
    
    double *a  // Zeiger auf doubles
    double a[] // Array von doubles
    double (*a)[] // Array von Zeigern auf doubles
    

    Du kannst es auch einfach zählen: Wieviele "Indirektionen" führen zum eigentlichen Wert:

    double a;  // => a ist bereits der Wert => 0 Indirektionen
    double *a  // => *a oder a[0] ist der Wert => 1 Indirektion
    double (*a)[]  // => **a oder (*a)[0] oder a[0][0] ist der Wert => 2 Indirektionen
    

    @Vorgehen: Du solltest noch etwas mahr Gehirnschmalz darein verwenden, zu verstehen und Dich weniger auf imitieren verlassen.
    Das ist nicht böse gemeint, aber aus leidiger Erfahrung weiß ich, dass man vermeintliche schnelle Erfolge durch imitieren später blutig bezahlen muss.... 😉

    Gruß,

    Simon2.


  • Mod

    void foo(int (*p)[]);
    

    Der Parameter dieser Funktion ist Zeiger auf Array unbekannter Größe aus int (d.h. das Objekt, auf das gezeigt wird, hat einen unvollständig deklarierten Typ). Die einzige Möglichkeit, einen solchen Zeiger zu bilden, besteht in der Benutzung eines Casts [edit:]. Keine der gezeigten Varianten (auch die nicht, die der Compiler durchlässt) stellen Standard-C++ dar.

    Nicht zu verwechseln ist dieser Fall mit dem, wenn der Top-Level-Deklarator (aber eben nur dieser) eines Parameters bzw. Rückgabetyps ein Array bezeichnet - in diesem Falle wird der Typ angepasst zu Zeiger auf T:

    Die Funktion

    func(Mat A, int row, int* ncols, const int (*cols)[], const double (*vals)[]);
    

    Erwartet für cols und vals also zwei Zeiger auf Arrays, da es keine implizite Konvertierung von Zeigern auf Arrays fester Größe in Zeiger auf Arrays unbestimmter Größe gibt, muss ein Cast her:

    int row;
    int ncols;
    const int    cols[..];
    const double vals[..];
    func(A,row,ncols,reinterpret_cast<const int(*)[]>(&cols),reinterpret_cast<const double(*)[]>(&vals));
    

    cols und vals könnten hier nat. Zeiger sein, ohne dass sich die Syntax des Funktionsaufrufs ändert. Wegen des Casts, spielt es auch keine Rolle, ob die Zeiger nun Zeiger auf das erste Element oder das Array selbst sind.



  • Also nochmal zu deutsch:

    die Methode:

    const int* cols;
    const double* vals;
    

    in

    func(A,row,ncols,const int (*cols)[],const double (*vals)[]);
    

    einzusetzen, indem ich

    func(A,row,&ncols,&cols,&vals);
    

    wähle, ist eigentlich nicht "Standard", geht aber (wird so von der Library angegeben).

    Was ist ein "Top-Level-Deklarator"?

    "Da es keine implizite Konvertierung von Zeigern auf Arrays fester Größe in Zeiger auf Arrays unbestimmter Größe gibt, muss ein Cast her!"

    Aha!

    Deine Version:

    const int    cols[ncols];
    const double vals[ncols];
    

    einzusetzen, wäre also die Richtige! da man aber "ncols" vor dem Funktionsaufruf nicht kennt, kann man das umgehen, indem man einen Pointer nimmt. D.h. intern (in der Funktion) wird mit Sicherheit die Version mit dem Cast zu finden sein:

    func(A,row,ncols,reinterpret_cast<const int(*)[]>(&cols),reinterpret_cast<const double(*)[]>(&vals));
    

    Wenn das so ist, dann danke ich! 🙂


Log in to reply