2D array in subroutine alloziieren
-
Hallo,
ich kann ein 2D Array so alloziieren und verwenden:float **testf; int nx=10; int ny=2; testf = (float **) malloc(nx * sizeof(float*)); //allocate rows testf[0]=(float *) malloc((nx*ny)*sizeof(float));//allocate array //set the address per row for(i=1; i<nx;i++){ testf[i]=testf[i-1]+ny; } //fill in some data for(i=0; i < nx; i++) { testf[i][0] = (float) i; testf[i][1] = (float) i*10; } printf("test %f \n",testf[5][0]); printf("test %f \n",testf[5][1]);
nun will ich das ganze in einer subroutine machen:
float ** testf; test2da(testf); /*printf hier gibt mist aus*/ void test2da(float **a2d){ int nx=10; int ny=2; testf = (float **) malloc(nx * sizeof(float*)); //allocate rows testf[0]=(float *) malloc((nx*ny)*sizeof(float));//allocate array //set the address per row for(i=1; i<nx;i++){ testf[i]=testf[i-1]+ny; } //fill in some data for(i=0; i < nx; i++) { testf[i][0] = (float) i; testf[i][1] = (float) i*10; } /*printf hier gibt korrekte daten aus*/ }
innerhalb der subroutine stimmen die daten, außerhalb nicht. ich denke ich muß
den Float ** pointer anders übergeben, konnte aber nicht herausfinden wie.hat jemand nen hinweis?
Danke!
-
Ja, du mußt ihn per Zeiger übergeben:
void test2da(float** * pa)//Zeiger auf ein 2D-Array 'float**' { *pa = malloc(nx*sizeof(float*); ... } float** testarray; test2da(&testarray);
-
ich komme immer noch nicht klar mit den weiteren *:
void test2da(float **a2d){ int nx=10; int ny=2; *testf = (float **) malloc(nx * sizeof(float*)); //allocate rows /* in den folgenden zeilen: */ /* [0] erspart mir normalerweise den *; aber in diesem Fall? */ /* und brauch ich ein float * ? */ testf[0]=(float *) malloc((nx*ny)*sizeof(float));//allocate array //set the address per row for(i=1; i<nx;i++){ testf[i]=testf[i-1]+ny; } //fill in some data for(i=0; i < nx; i++) { testf[i][0] = (float) i; testf[i][1] = (float) i*10; } /*printf hier gibt korrekte daten aus*/ }
ich habe ein paar kombinationen ausprobiert aber immer seg.faults bekommen.
(ich arbeite normal in fortran, da sind die array sooo schön leicht zu haben)
Alex
-
Ja, wenn du ihn nicht angibst, kann er auch nicht funktionieren (btw solltest du daran denken, daß du dann auch eine zusätzliche Dereferenzierung brauchst):
void test2da(float ***a2d){ int nx=10; int ny=2; *a2d = (float **) malloc(nx * sizeof(float*)); //allocate rows /* in den folgenden zeilen: */ /* [0] erspart mir normalerweise den *; aber in diesem Fall? */ /* und brauch ich ein float * ? */ (*a2d)[0]=(float *) malloc((nx*ny)*sizeof(float));//allocate array //set the address per row for(i=1; i<nx;i++){ (*a2d)[i]=testf[i-1]+ny; } ... }
Alternativ kannst du das Array auch lokal anlegen und erst am Ende die Adresse übergeben:
void test2da(float ***pa) { int nx=10,ny=2; float** a2d = malloc(nx*sizeof(float*)); ... *pa = a2d; }
(btw, ist die spontane Umbenennung des Parameters von 'a2d' nach 'testf' ein C&P-Fehler oder steht das tatsächlich so in deinem Programm?)
-
also die umbenennung ist ein c&p fehler.
wenn ich oben in zeile 14 (13-15):
for(i=1; i<nx;i++){ (*a2d)[i]=(*a2d)[i-1]+ny; }
verwende funktioniert der code [(*) hat noch gefehlt.
Jetzt frage ich mich, ob es nicht
(*a2d)[i]=(*a2d)[i-1]+ny*sizeof(float));
heißen müßte? Ich will ja die startadresse für die zeile festlegen...
alex
-
Nein, muß es nicht. Das sizeof(float) wird von der Zeiger-Arithmetik schon mit einberechnet.
-
Wir wissen zwar nicht, was der nette Nachbar von nebenan empfiehlt, aber man könnte das so machen:
#include <stdio.h> int main() { int nx = 10, ny = 2; int x, y; float** arr2D; arr2D = malloc( 10 * sizeof( float* ) ); for ( x = 0; x < nx; x++ ) { arr2D[x] = malloc( ny * sizeof( float ) ); } // Array initialisieren ( ja, man kann gleich calloc benutzen ) for ( x = 0; x < nx; x++ ) { for ( y = 0; y < ny; y++ ) { arr2D[x][y] = 0.0; } } // Werte anzeigen puts("Zeige 10 * 2 Matrix\n\n"); for ( x = 0; x < nx; x++ ) { for ( y = 0; y < ny; y++ ) { printf("%f ", arr2D[x][y] ); } puts(""); } puts(""); return 0; }
MfG
-
Der noch nettere Nachbar schrieb:
Wir wissen zwar nicht, was der nette Nachbar von nebenan empfiehlt, aber man könnte das so machen:
Soll ich dir etwas verraten: Da finde ich die Lösung des OP um einiges eleganter
(und außerdem ging es hier nicht um die Frage, wie das 2D-Array angelegt werden soll, sondern darum, wie man es von einer Funktion ans Hauptprogramm übergeben kann)
-
daß ich das sizeof(float) nicht brauche hab ich gerade auch festgestellt...
da fehlt mir ein bischen die erfahrung mit der pointerarithmetik...Danke!
Alex
-
Ok, dann verrate ich dir auch etwas, ich finde das viel zu umständlich.
Vielleicht ein nettes Gedankenspiel, wenn man gerade mal Langeweile hat, mehr aber auch nicht.
-
Der noch nettere Nachbar schrieb:
Ok, dann verrate ich dir auch etwas, ich finde das viel zu umständlich.
Vielleicht ein nettes Gedankenspiel, wenn man gerade mal Langeweile hat, mehr aber auch nicht.Wieso umständlich? Da muß man nur zwei Speicherblöcke anfordern und damit auch nur diese zwei Speicherblöcke wieder freigeben. Und außerdem hat man den Vorteil, daß das gesamte Array am Stück im Speicher liegen hat.
Mal zum Vergleich beide Varianten gegenübergestellt:
//Beginner's Variante: testf = malloc(nx * sizeof(float*)); //allocate rows testf[0] = malloc((nx*ny)*sizeof(float));//allocate array for(i=1; i<nx;i++) testf[i]=testf[i-1]+ny; ... free(testf[0]);free(testf); //Nachbar's Variante: testf = malloc( nx * sizeof( float* ) ); for ( x = 0; x < nx; x++ ) testf[x] = malloc( ny * sizeof( float ) ); ... for(x=0;x<nx;x++) free(testf[x]); free(testf);
-
Ja, umständlich von der Denkweise her.
Wenns darum geht, mit Speicherblöcken zu knapsen, dann kann ich ja auch gleich einen einzigen Block nehmen:#include <stdio.h> #include <stdlib.h> int main() { int nx = 10, ny = 2, x, y; float* arr2d = malloc ( nx*ny*sizeof(float) ); for ( x = 0; x < nx; x++ ) { for ( y = 0; y < ny; y++ ) { arr2d[x*ny+y] = x*ny+y; } } // Zeige arr2d for ( x = 0; x < nx; x++ ) { for ( y = 0; y < ny; y++ ) { printf("%5.1f ", arr2d[x*ny+y]); } puts(""); } free( arr2d ); return 0; }
Bei einem Verlgleich ergibt sich:
//Beginner's Variante: testf = malloc(nx * sizeof(float*)); //allocate rows testf[0] = malloc((nx*ny)*sizeof(float));//allocate array for(i=1; i<nx;i++) testf[i]=testf[i-1]+ny; ... free(testf[0]);free(testf); //Nachbar's zweite Variante: float* arr2d = malloc ( nx*ny*sizeof(float) ); ... free( arr2d );
-
Ja, die Variante ist tatsächlich noch etwas besser - nur mußt du daran denken, den Index selber zu berechnen (wobei, im Ernstfall würde ich die gesamte Logik sowieso hinter einer Matrix-Klasse* verstecken, die sich über solche Details Gedanken macht)
* bzw. einer Matrix-Bibliothek