2D Array an Funktion übergeben



  • kA schrieb:

    Wasn jetz?

    Wiso willst du pointer benutzen?
    Ich würde die ganze funktion eh komplett anders schreiben...

    ...aber soooo, neimals...

    edit: aso, is vorgegeben...



  • richtig 😉 es ist vorgegeben



  • Hehe... so kompilierts meiner...

    ...aber ob du was damit anfangen kannst, kA xD

    double d1[4][4], d2[4][4], d3[4][4];
    void mul(double *d1[4][4], double *d2[4][4], double *d3[4][4])
    {
    }
    int main ()
    {
    mul((double *(*)[4]) d1, (double *(*)[4]) d2, (double *(*)[4]) d3);
    return 0;
    }
    


  • Wenn man reinterpret_cast nicht mag und nicht vorgeschrieben ist, wie die Variablen deklariert werden sollen:

    double *d1[4], *d2[4], *d3[4];
    void mul(double *d1[4][4], double *d2[4][4], double *d3[4][4])
    {
    }
    int main ()
    {
        //2D-Arrays initialisieren
        mul(&d1, &d2, &d3);
    }
    


  • kA schrieb:

    Hehe... so kompilierts meiner...

    ...aber ob du was damit anfangen kannst, kA xD

    double d1[4][4], d2[4][4], d3[4][4];
    void mul(double *d1[4][4], double *d2[4][4], double *d3[4][4])
    {
    }
    int main ()
    {
    mul((double *(*)[4]) d1, (double *(*)[4]) d2, (double *(*)[4]) d3);
    return 0;
    }
    

    Hm da bekomm ich schon mal die Startadresse und er macht ein 2D Array daraus, aber die Werte die dann in dem Array stehen passen nicht.

    @schorsch code naja die funktion mul steht in ner anderen Datei von daher klappt das mit der globalen Deklaration nicht



  • pad8626 schrieb:

    @schorsch code naja die funktion mul steht in ner anderen Datei von daher klappt das mit der globalen Deklaration nicht

    😕 Was hat die "andere Datei" mit einer globalen Deklaration für ein Problem?
    😕 Welche Rolle spielt es für den Aufruf, dass die Variablendeklaration beispielshalber global ist?
    😕 Ist die Deklaration in kAs Beispiel nicht ebenso global?
    😕 Was sagt der Compiler?


  • Mod

    pad8626 schrieb:

    Hi ich hoffe das ist die richtige Kategorie für das Thema.

    Ich hab zwei vorgegebene Funktionköpfe:

    void mul(double* m1[4][4], double* m2[4][4], double* result[4][4])
    
    void add(double* m1[4][4], double* m2[4][4], double* result[4][4])
    

    ich soll also aus meinem Hauptprgoramm drei 2D Felder übergeben aber ich bekomm es einfach net hin. Wie würde ein Bsp. aussehen wenn ich z.B:

    double m1[4][4], m2[4][4], res[4][4];
    

    die drei Felder hab und Sie an die Funktion "mul" übergeben will.

    Das geht nicht. Deine Variablen sind 2-dimensionale Arrays mit dem Elementtyp double. Die Funktionen erwarten dagegen 2-dimensionale Arrays (genauer: Pointer auf eindimensionale Arrays, aber dieser Unterschied spielt hier keine Rolle) mit dem Elementtyp Pointer auf double. Die Aufgabe muss hier scheitern, und kein noch so kreatives und sinnfreies Herumcasten wird daran etwas ändern.



  • ich hab mir mal ein test programm geschrieben

    #include "stdafx.h"
    
    using namespace std;
    
    void test(double* [4][4]);
    
    void main()
    {
    
    	double m1[4][4]={1,2,3,4,5,6,7,8,9,1,2,3,5,1,1,1};
    	double* m1P = &m1[0][0];
    
    	for(int i=0; i<16; i++)
    	{
    		printf("%p %lf\n",m1P,*m1P++);
    	}
    
    	printf("\n\n");
    
    	test((double*(*)[4])m1);
    }
    
    void test(double* m1P[4][4])
    {
    
    	for(int i=0; i<16; i++)
    	{
    		printf("%p %lf\n",m1P,*m1P++);
    	}
    	_getch();
    }
    

    So wie gesagt funtzt so weit nur die werte stimme nicht

    Und hier ist es wie es in der aufgabe sein soll

    Matrix.h

    #ifndef MATRIX_H 
    #define MATRIX_H
    
    void mul(double* [4][4] , double* [4][4], double* [4][4]);
    void add(double* [4][4], double* [4][4], double* [4][4]); 
    
    #endif
    

    Matrix.cpp

    #include "stdafx.h"
    
    void mul(double* m1[4][4], double* m2[4][4], double* [4][4])
    {
    
    }
    
    void add(double* m1[4][4], double* m2[4][4], double* [4][4])
    {
    
    }
    

    Programm

    ...
    
    double m1[4][4]={1}, m2[4][4]={1}, res[4][4]={1};
    
    		system("cls");
    
    		printf("Matrix\
                  \n======\n\n");
    
    		mul( (double*(*)[4])m1 , (double*(*)[4])m2 , (double*(*)[4])res);        
    
    ...
    

    So da funktioniert das von KA aber die Werte stimmen halt nicht



  • camper schrieb:

    pad8626 schrieb:

    Hi ich hoffe das ist die richtige Kategorie für das Thema.

    Ich hab zwei vorgegebene Funktionköpfe:

    ```cpp
    void mul(double
    m1[4][4], double
    m2[4][4], double* result[4][4])

    void add(double* m1[4][4], double* m2[4][4], double* result[4][4])

    **  
    ich soll also aus meinem Hauptprgoramm drei 2D Felder übergeben aber ich bekomm es einfach net hin. Wie würde ein Bsp. aussehen wenn ich z.B:  
      
    
    ```cpp
    double m1[4][4], m2[4][4], res[4][4];
    

    NICHT VORGEGEBEN

    die drei Felder hab und Sie an die Funktion "mul" übergeben will.

    Das geht nicht. Deine Variablen sind 2-dimensionale Arrays mit dem Elementtyp double. Die Funktionen erwarten dagegen 2-dimensionale Arrays (genauer: Pointer auf eindimensionale Arrays, aber dieser Unterschied spielt hier keine Rolle) mit dem Elementtyp Pointer auf double. Die Aufgabe muss hier scheitern, und kein noch so kreatives und sinnfreies Herumcasten wird daran etwas ändern.

    Du siehst ja was vorgegeben ist das muss ja irgendwie funktionieren vielleicht muss man dann halt die Felder anders deklarieren aber wie??

    Jetzt weiß ich gar net mehr weiter



  • pad8626 schrieb:

    Du siehst ja was vorgegeben ist das muss ja irgendwie funktionieren vielleicht muss man dann halt die Felder anders deklarieren aber wie??

    Hab ich doch gesagt:

    //Deklaration
    double *m1[4], *m2[4], *res[4];
    
    //Aufruf
    mul(&m1, &m2, &res);
    


  • kompilieren tut er es aber ich kann nur die ersten vier Werte beschreiben. Aber die restlichen 12 da sagt er zu viele Initialisierungen.


  • Mod

    pad8626 schrieb:

    camper schrieb:

    pad8626 schrieb:

    Hi ich hoffe das ist die richtige Kategorie für das Thema.

    Ich hab zwei vorgegebene Funktionköpfe:

    ```cpp
    void mul(double
    m1[4][4], double
    m2[4][4], double* result[4][4])

    void add(double* m1[4][4], double* m2[4][4], double* result[4][4])

    **  
    ich soll also aus meinem Hauptprgoramm drei 2D Felder übergeben aber ich bekomm es einfach net hin. Wie würde ein Bsp. aussehen wenn ich z.B:  
      
    
    ```cpp
    double m1[4][4], m2[4][4], res[4][4];
    

    NICHT VORGEGEBEN

    die drei Felder hab und Sie an die Funktion "mul" übergeben will.

    Das geht nicht. Deine Variablen sind 2-dimensionale Arrays mit dem Elementtyp double. Die Funktionen erwarten dagegen 2-dimensionale Arrays (genauer: Pointer auf eindimensionale Arrays, aber dieser Unterschied spielt hier keine Rolle) mit dem Elementtyp Pointer auf double. Die Aufgabe muss hier scheitern, und kein noch so kreatives und sinnfreies Herumcasten wird daran etwas ändern.

    Du siehst ja was vorgegeben ist das muss ja irgendwie funktionieren vielleicht muss man dann halt die Felder anders deklarieren aber wie??

    Jetzt weiß ich gar net mehr weiter

    Es gibt mehrere Möglichkeiten. Letzlich hängt das davon ab, welche Anforderungen die Funktionen an ihre Parameter stellen. Eine denkbare Variante ist jedenfalls, für den Funktionsaufruf ein Hilfsarray p mit dem korrekten Typ für die Funktion (also mit dem Elementtyp Pointer auf double) zu kreieren, und zwar mit dem Inhalt, dass für jedes p[i][j] gilt:
    p[i][j] == &a[i][j] (a ist das Ausgangsarray)
    Dies wird für alle Parameter der Funktion durchgeführt und diese dann mit den 3 Hilfsarrays aufgerufen.
    also

    const int N = 4, M = 4;
    void mul_helper(double m1[N][M], double m2[N][M], double result[N][M])
    // oder auch void mul_helper(double (&m1)[N][M], double (&m2)[N][M], double (&result)[N][M]), wenn man etwas ausdrücklicher formulieren will
    {
        double* pm1[N][M], *pm2[N][M], *presult[N][M]:
        for ( int i = 0; i < N; ++i )
            for ( int j = 0; j < M; ++j )
            {
                pm1[i][j] = &m1[i][j];
                pm2[i][j] = &m2[i][j];
                presult[i][j] = &mresult[i][j];
            }
        mul( pm1, pm2, presult );
    }
    

    schorsch code schrieb:

    pad8626 schrieb:

    Du siehst ja was vorgegeben ist das muss ja irgendwie funktionieren vielleicht muss man dann halt die Felder anders deklarieren aber wie??

    Hab ich doch gesagt:

    //Deklaration
    double *m1[4], *m2[4], *res[4];
    
    //Aufruf
    mul(&m1, &m2, &res);
    

    syntaktisch ja, inhaltlich blödsinn. denn hier hast du ja von vornherein nur ein eindimensionales array. die fehlende zweite dimension wird der compiler hoffentlich mit einem segfault belohnen.



  • glaub kaum das unser prof das unbedingt wollte das wir noch sone zusatz Funktion schreiben sonst hätte er das mit in die Aufgabe geschrieben



  • camper schrieb:

    schorsch code schrieb:

    pad8626 schrieb:

    Du siehst ja was vorgegeben ist das muss ja irgendwie funktionieren vielleicht muss man dann halt die Felder anders deklarieren aber wie??

    Hab ich doch gesagt:

    //Deklaration
    double *m1[4], *m2[4], *res[4];
    
    //Aufruf
    mul(&m1, &m2, &res);
    

    syntaktisch ja, inhaltlich blödsinn. denn hier hast du ja von vornherein nur ein eindimensionales array. die fehlende zweite dimension wird der compiler hoffentlich mit einem segfault belohnen.

    Oh, da bin ich aber überrascht 😮
    Warum sollte das folgende Beispiel mit einem segfault belohnt werden 😕

    #include <iostream>
    using namespace std;
    
    void print_matrix(double *m[4][4])
    {
        for(int i = 0; i < 4; ++i)
        {
            for(int j = 0; j < 4; ++j)
                cout << (*m)[i][j] << " ";
            cout << "\n";
        }
    }
    
    int main()
    {
        double *m1[4];
    
        //Speicher für m1 reservieren
        for(int i = 0; i < 4; ++i)
            m1[i] = new double[4];
    
        //m1 initialisieren    
        for(int i = 0; i < 4; ++i)
            for(int j = 0; j < 4; ++j)
                m1[i][j] = .5;
    
        print_matrix(&m1);
    
        //Speicher von m1 freigeben
        for(int i = 0; i < 4; ++i)
            delete [] m1[i];
    }
    


  • Selbstverständlich kann man (falls es doch keinen segfault gibt) reservieren und initialisieren auch zusammenfassen:

    //Speicher für m1 reservieren und m1 initialisieren
        for(int i = 0; i < 4; ++i)
        {
            m1[i] = new double[4];
            for(int j = 0; j < 4; ++j)
                m1[i][j] = .5;
        }
    

  • Mod

    schorsch code schrieb:

    Warum sollte das folgende Beispiel mit einem segfault belohnt werden 😕

    #include <iostream>
    using namespace std;
    
    void print_matrix(double *m[4][4])
    {
        for(int i = 0; i < 4; ++i)
        {
            for(int j = 0; j < 4; ++j)
                cout << (*m)[i][j] << " ";
            cout << "\n";
        }
    }
    
    int main()
    {
        double *m1[4];
        
        //Speicher für m1 reservieren
        for(int i = 0; i < 4; ++i)
            m1[i] = new double[4];
        
        //m1 initialisieren    
        for(int i = 0; i < 4; ++i)
            for(int j = 0; j < 4; ++j)
                m1[i][j] = .5;
                
        print_matrix(&m1);
        
        //Speicher von m1 freigeben
        for(int i = 0; i < 4; ++i)
            delete [] m1[i];
    }
    

    Wird es nicht. Ich habe allerdings große Zweifel, dass mul und add so dereferenzieren, wie du das in print_matrix getan hast.

    camper schrieb:

    Letzlich hängt das davon ab, welche Anforderungen die Funktionen an ihre Parameter stellen.

    Wahrscheinlicher würde das dort eher wie *m[i][j] aussehen - nur das korrespondiert sinnvoll mit der Deklaration von add und mul. Im Grunde ist deine Deklaration von print_matrix eine Lüge, die nur auf Grund der Eigenheiten von C++ hinsichtlich des Verhältnisses von Arrays und Pointern nicht unmittelbar im Desaster endet.



  • Jetzt blick ich gar net mehr durch kann mir das noch mal einer für mein Problem übersetzen HEHE



  • Es muss bekannt sein, ob die Funktionen mul und add ihre Parameter dereferenzieren, bevor die Index-Operatoren benutzt werden. Der Index-Operator (die eckigen Klammern) hat eine höhere Priorität als der Dereferenzierungsoperator (das Sternchen). Das heißt ohne die Benutzung von Klammern kommen die eckigen Klammern zuerst und dann die Dereferenzierung, also würden dann in m[i][j] Zeiger erwartet werden.
    Eine Tabelle mit der Operatorenrangfolge gibt es z. Bsp. hier.

    Was dein Problem betrifft, fallen mir 3 Möglichkeiten ein:

    1.) Falls dir der Quelltext von mul und add zur Verfügung steht, nachsehen wie dereferenziert wird.
    2.) Schauen, ob es diesbezüglich eine Beschreibung der Schnittstellen gibt.
    3.) Trial & Error (Ausprobieren und Fehler korrigieren)



  • das einzige was bekannt ist ist die aufgabenstellung ^^

    **
    5.
    (Kategorie Schwer, 4 Punkte) Legen Sie die Dateien matrix.cpp und matrix.h an. Implementieren Sie eine 4x4 Matrizenmultiplikation und eine 4x4 Matrizenaddition. Die Routinen sollen dabei folgende Signatur haben:

    void mul(double& m1[4][4], double& m2[4][4], double& result[4][4]) …

    void add(double& m1[4][4], double& m2[4][4], double& result[4][4]) …

    Machen Sie sich den Grund für diese Schreibweise klar. Sie zwingen nämlich den Benutzer dazu, nicht nur zwei Matrizen für die Rechnung, sondern auch eine Matrix für das Ergebnis anzugeben. Somit reservieren nicht SIE den Speicher für diese Matrix in IHRER Routine, sondern Sie zwingen den Benutzer dazu, die Matrizen selbst anzulegen und auch wieder zu löschen. Andernfalls würden Sie nämlich die Matrix erzeugen und der Benutzer die Matrix löschen und schon wären wir bei einem typischen Problem der Speicherreservierung. Woher soll der Benutzer wissen, dass er die Matrix selbst löschen muss? In der Regel kennt der Benutzer nicht Ihre .cpp Dateien. Testen Sie Ihre Routinen in der main Routine.
    **

    allerding stehen hier noch & operatoren das hat er korrigiert da müssen * hin



  • camper schrieb:

    Im Grunde ist deine Deklaration von print_matrix eine Lüge

    @camper:
    Probier mal, die Deklaration des Beispiels zu bekehren:

    void print_matrix(double **m[4]);
    

    Wenn ich &m1 an eine solche (wahre???) Deklaration übergebe, erfreut das den Compiler nicht gerade:

    g++ schrieb:

    error: cannot convert `double* ()[4]' to `double**' for argument `1' to `void print_matrix(double***)'

    Lügt der Compiler etwa 😕 Was fällt ihm ein zu behaupten, ich würde double ***m statt double **m[4] erwarten 😕

    (Trug-?)Schlussfolgerung: Leider kann der Compiler in diesem Fall die Wahrheit nicht vertragen.


Anmelden zum Antworten