2010-01-24 7 views
8

je veux allouer une matrice.allouer la matrice dans C

est ce la seule option:

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

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

[Ne pas convertir le résultat de malloc en C] (http: // stackoverflow.com/q/605845/995714) –

Répondre

20

Eh bien, vous ne nous avez pas une mise en œuvre complète. Je suppose que tu voulais dire.

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

est ici une autre option:

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

Ensuite, vous simulez la matrice en utilisant

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

pour la commande de la ligne-major et

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

pour la commande de colonne-major . L'une de ces deux options est actuellement la manière préférée de gérer une matrice en C. C'est parce que maintenant la matrice sera stockée de manière contiguë en mémoire et vous bénéficierez de locality of reference. Fondamentalement, le cache CPU sera beaucoup plus heureux avec vous.

+1

si votre compilateur supporte des tableaux de longueur variable ou si 'cols' est une constante à la compilation, vous n'avez même pas besoin de calculer vous-même les offsets; si vous utilisez int (* mat) [cols] = malloc (rows * sizeof * mat) ', vous pouvez accéder aux éléments via' mat [i] [j] 'et utiliser toujours un bloc de mémoire contigu – Christoph

+1

Même en ignorant les performances Une seule allocation est également préférable car c'est plus simple. Il y a moins de choses à désallouer plus tard, et il n'est pas nécessaire de gérer les échecs d'allocation partielle. – jamesdlin

+1

Cela ne serait-il pas un problème si chaque malloc créait des blocs de mémoire discontinus, rendant leurs adresses non sérielles? Par exemple, le premier malloc pourrait renvoyer le pointeur 0x635 et les autres mallocs pourraient renvoyer des pointeurs 0xA279, 0xB7DD, etc. Si cela se produisait, un calcul simple comme indiqué ci-dessus ne fonctionnerait pas. –

2

Que diriez-vous juste:

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

Vous pouvez également utiliser calloc, qui initialisera également la matrice pour vous. La signature est légèrement différente:

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

Vous pouvez la réduire à un appel à malloc, mais si vous voulez utiliser un style de tableau 2D, vous devez encore la boucle.

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 testé, mais vous avez l'idée. Sinon, je m'en tiendrai à ce que suggère Jason.

+0

cela ne fonctionne que si 'sizeof (int) == sizeof (int *)' - sinon, le décalage sera faux; il peut effectivement être faux, même si c'est le cas – Christoph

+0

@Christoph: Bon point, et c'est facile à contourner, mais comme je l'ai noté dans ma réponse, ce n'est pas testé. Fixé ceci maintenant. –

-1

Pour un tableau N-dimensionnelle vous pouvez le faire:

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

Pour accéder à une cellule de tableau avec la façon typique, vous pouvez le faire:

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; 
} 

(Note: le test na pas maintenant, mais Traduit de mon code Matlab, mais dans Matlab index commence à partir de 1, donc je peux faire une erreur (mais je ne pense pas))

Amusez-vous!

3

ce que vous pouvez faire est

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

et utilisez alors cette nouvelle matrice comme mat [i] [j]