2D array in subroutine alloziieren



  • 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


Anmelden zum Antworten