2010-01-24 20 views
8

Voglio allocare una matrice.allocare matrice in C

è questa l'unica opzione:

int** mat = (int**)malloc(rows * sizeof(int*)) 

for (int index=0;index<row;++index) 
{ 
    mat[index] = (int*)malloc(col * sizeof(int)); 
} 
+1

[Non eseguire il cast di malloc in C] (http: // stackoverflow.it/q/605845/995714) –

risposta

20

Beh, non ci ha dato un'implementazione completa. Presumo che tu intendessi.

int **mat = (int **)malloc(rows * sizeof(int*)); 
for(int i = 0; i < rows; i++) mat[i] = (int *)malloc(cols * sizeof(int)); 

Ecco un'altra opzione:

int *mat = (int *)malloc(rows * cols * sizeof(int)); 

Poi, di simulare la matrice utilizzando

int offset = i * cols + j; 
// now mat[offset] corresponds to m(i, j) 

per l'ordinazione row-major e

int offset = i + rows * j; 
// not mat[offset] corresponds to m(i, j) 

per l'ordinazione column-major .

Una di queste due opzioni è in realtà il modo preferito di gestire una matrice in C. Questo perché ora la matrice verrà memorizzata in modo contiguo nella memoria e si beneficerà di locality of reference. Fondamentalmente, la cache della CPU sarà molto più felice con te.

+1

se il compilatore supporta matrici di lunghezza variabile o se 'cols' è una costante in fase di compilazione, non è nemmeno necessario calcolare da sé gli offset; se usi 'int (* mat) [cols] = malloc (righe * sizeof * mat)', puoi accedere agli elementi tramite 'mat [i] [j]' e utilizzare ancora un blocco contiguo di memoria – Christoph

+1

Anche ignorando le prestazioni anche una singola allocazione è preferibile perché è più semplice. Ci sono meno cose da deallocare più tardi, e non c'è bisogno di affrontare fallimenti di allocazione parziale. – jamesdlin

+1

Non sarebbe un problema se ogni malloc creasse blocchi di memoria discontinui, rendendo i loro indirizzi non seriali? Ad esempio, il primo malloc potrebbe restituire il puntatore 0x635 e gli altri mallocs potrebbero restituire i puntatori 0xA279, 0xB7DD, ecc. Se ciò accade, un semplice calcolo come detto sopra non funzionerebbe. –

2

ne dite solo:

int* mat = malloc(rows * columns * sizeof(int)); 
2

È anche possibile utilizzare calloc, che inoltre azzererà l'inizializzazione della matrice. La firma è leggermente diversa:

int *mat = (int *)calloc(rows * cols, sizeof(int)); 
0

È possibile comprimerla a una chiamata a malloc, ma se si desidera utilizzare uno stile di matrice 2D, è comunque necessario il ciclo for.

int** matrix = (int*)malloc(rows * cols * sizeof(int) + rows * sizeof(int*)); 

for (int i = 0; i < rows; i++) { 
    matrix[i] = matrix + rows * sizeof(int*) + rows * cols * sizeof(int) * i; 
} 

Non testato, ma si ottiene l'idea. Altrimenti, resterei fedele a ciò che Jason suggerisce.

+0

funziona solo se 'sizeof (int) == sizeof (int *)' - altrimenti, l'offset sarà errato; in realtà potrebbe essere sbagliato anche se questo è il caso – Christoph

+0

@Christoph: buon punto, e questo è facile da aggirare anche, ma come ho notato nella mia risposta, questo non è stato verificato. Risolto questo ora. –

-1

Per una matrice n-dimensionale si può fare questo:

int *matrix = malloc(D1 * D2 * .. * Dn * sizeof(int)); // Di = Size of dimension i 

Per accedere una cella array con il tipico modo si può fare questo:

int index = 0; 
int curmul = 1; 
int i; 
int indexes = {I1, I2, ..., In}; // Ii = Index in dimension i 

for(i = N-1; i >= 0; i--) { 
    index = index + indexes(i) * curmul; 
    curmul = curmul * Di; 
} 

(Nota: prova non ha ancora adesso, ma dovrebbe funzionare. Tradotto dal mio codice Matlab, ma in Matlab indice parte da 1, così che io possa fatto un errore (ma io non la penso così))

Buon divertimento!

3

che cosa si può fare è

int (*mat)[col]; 
mat=(int (*)[col])malloc(sizeof(*mat)*row); 

e quindi utilizzare questa nuova matrice come mat [i] [j]