Newsgroup: it.comp.lang.c
Titolo: Matrici allocate dinamicamente

Salve,
Vorrei riuscire a scrivere una funzione che prende in ingresso una matrice
(var. globale) MxN (valori costanti predefiniti) e ne restituisce una che è
una copia (opportunnamente modificata) di questa, allocata dinamicamente in
modo da poter essere distrutta a tempo debito.
Ovviamente entrano e econo dei puntatori a matrice, ma io vorrei che fosse
possibile accedere alla matrice restituita direttamente tramite indici del
tipo [i][j].
Come parametro di ingresso so che è lecito scrivere tutta la matrice:
 funz(int m_in[M][N])
essendo convertita in un puntatore automaticamente, ma quale tipo di
variabile m_out deve puntare alla memoria allocata all'interno della
funzione:
m_out=malloc(M*N*sizeof(int));
in modo da creare la nuova matrice e poi restituirla (return m_out) ?
Se utilizzo (*int)  quello che restituisco è un puntatore ad array e quindi
posso indicizzarlo solo una volta.
Se utilizzo (**int)  o (int[M][N]) non funziona niente (anzi si blocca
tutto).
Spero di essere stato chiaro.
Grazie
Andrea Giannone

in modo da creare la nuova matrice e poi restituirla (return m_out) ?
La seguente versione dovrebbe andare bene :
#include <stdlib.h>
#define M   50
#define N   20
int **funzione ( int m_in[M][N] )
{
      int **m_out, i, j ;
      m_out = malloc( M * sizeof( int * ) ) ;
      for ( i = 0 ; i < N ; i++ )
          m_out [i] = malloc( N * sizeof ( int ) ) ;
      for ( i = 0 ; i < M ; i++ )
          for ( j = 0 ; j < N ; j++ )
              m_out[i][j] = m_in[i][j] ;
      return m_out ;
}
--------------------------------------------------------
* Andrea Laforgia        (
andrea_...@bigfoot.com
) *
--------------------------------------------------------

Effettivamente la "doppia allocazione" era la soluzione giusta !
Adesso per liberare la memoria dovrebbe bastare:
new_m=funzione(m);
[...]
free(new_m);
o mi sbaglio?
Grazie dell' aiuto, ti devo un favore  ;-)
A.G.
-------------------------------------------------------


in modo da creare la nuova matrice e poi restituirla (return m_out) ?
      for ( i = 0 ; i < N ; i++ )
          m_out [i] = malloc( N * sizeof ( int ) ) ;
..ops... ovviamente il ciclo giusto e' il seguente :
      for ( i = 0 ; i < M ; i++ )
          m_out [i] = malloc( M * sizeof ( int ) ) ;


 
mi sa che č meglio:
	for( i = 0 ; i < M ; i++ )
	   m_out [i] = malloc( N * sizeof (int) ) ;
;-)
A.G.

 o mi sbaglio?
beh, mi sa che ti sbagli :-)
Il codice che ti è stato proposto prevede due "fasi" di allocazione della
memoria: una prima in cui viene allocata new_m, che puoi immaginare come un
array di M puntatori che puntano le righe della matrice, che vengono
allocate nella seconda fase, e che contengono i dati veri e propri. Per cui
se fai un free(new_m) senza prima aver disallocato le righe, ottieni un
risultato parziale, anzi, perdi l'unico riferimento che avevi alla memoria
allocata per esse e che può permetterti di disallocarle... memory leak! Per
cui fai così:
for( i = 0 ; i < M ; i++ )
   free(m_out [i]);
free(new_m);
Questo perchè in genere M+1 allocazioni pretendono M+1 disallocazioni.
Diverso sarebbe stato il caso in cui tu avessi deciso di allocare memoria
flat, ovvero con una bella
int *new_m;
new_m= malloc(M*N*sizeof(*new_m));
che disallochi semplicemente con una
free(new_m);
ma in questo modo perdi la possibilità di utilizzare l'indirizzamento
diretto per riga e colonna con le quadre [][] e devi farti le
moltiplicazioni per l'indirizzamento da solo. Perdi in leggibilità e
maneggevolezza, guandagando in performance, minor memory fragmentation e
memory usage.
A te la scelta....
Lorenzo Tanganelli