array c pointers matrix dynamic malloc

dynamic array c++



Función para asignar dinámicamente la matriz (4)

El problema aquí es que está transfiriendo mat a la función de asignación, que no puede retener la memoria asignada de la función al regresar, ya que C usa el valor de pasada para el paso del argumento de función.

Debe pasar un puntero a mat y asignar en consecuencia.

Quiero crear una función para asignar (con malloc / calloc ) una matriz declarada como un doble puntero. Entendí cómo funciona una matriz de doble puntero y cómo se asigna con malloc , pero cuando paso mi matriz (declarada en main() e inicializada a NULL ) mi programa se bloquea. Supongo que el error está en mi función allocMatrix() porque si allocMatrix() la matriz en main todo funciona sin problemas. Gracias :-)

Principal:

#include <stdio.h> #include <stdlib.h> #include "Data.h" #define ROW 5 #define COL 5 int main(void) { int i,j, ret; int nRow, nCol; int **mat=NULL; // double pointer matrix nRow = 0; nCol = 0; //Insert n of row and columns printf("Insert n of rows and columns:/n"); scanf("%d %d", &nRow, &nCol); //Functions to allocate matrix ret=allocMatrix(mat, nRow, nCol); printf("Return value: %d/n",ret); /* this code works perfect! mat= malloc(nRow * sizeof(int)); i=0; while( i < nRow) { mat[i]=malloc(nCol * sizeof(int)); i++; } */ //Get Values from stdin i=0; while( i < nRow) { j=0; while (j < nCol) { printf("Insert value pos[%d,%d]:/n", i, j); scanf("%d", &mat[i][j]); j++; } i++; } //Print values i=0; while (i < nRow) { j=0; while( j < nCol) { printf("Value pos[%d,%d] is: %d /n", i, j, mat[i][j]); j++; } i++; } system("pause"); return EXIT_SUCCESS; }

Función allocateMatrix :

int allocMatrix(int **matrix, int nRow, int nCol) { int i; int ext_status; //Classic allocation method for matrix matrix= malloc( nRow * sizeof(int)); if ( matrix != NULL) { i=0; while (i < nRow) { matrix[i]= malloc(nCol * sizeof(int)); if( matrix[i] != NULL) ext_status= 1; else ext_status= 0; i++; } } else ext_status= 0; return ext_status; }


Estás pasando la matriz a allocMatrix por valor, cuando debería ser por referencia.

Define tu función como int allocMatrix(int ***matrix, int nRow, int nCol) y reemplaza la matrix con *matrix (por cierto, cuidado con la sintaxis para la indexación, debe ser (*matrix)[i] , not *matrix[i] ).

Esto significa que llamará a esta función como allocMatrix(&mat, nRow, nCol) .


Nunca utilice puntero a puntero para asignar matrices multidimensionales. Es una práctica extendida pero mala e incorrecta. Si lo haces, no obtendrás una verdadera matriz 2D, y generará un código más lento debido a la fragmentación del montón. También hace que el código sea más difícil de escribir, leer y mantener, lo que a su vez aumenta el potencial de pérdidas de memoria.

En su lugar, asigne la matriz 2D correctamente en celdas de memoria adyacentes, como esta:

int x; int y; // store some values in x and y here int(*matrix)[y] = malloc (sizeof(int[x][y])); if(matrix == NULL) { // error handling here } matrix[i][j] = something; // do something with the matrix free(matrix);

Si insiste en mantener este código en una función, entonces sería:

void* allocMatrix (int nRow, int nCol) { return malloc (sizeof(int[nRow][nCol])); } int(*matrix)[y] = allocMatrix(x, y);

Editar: explicación del código y punteros de matriz.

En la línea int(*matrix)[y] = malloc (sizeof(int[x][y])); , el sizeof(int[x][y]) es bastante directo, es simplemente el tamaño de una matriz 2D de ints con dimensiones x * y. Utiliza el concepto de matrices de longitud variable del estándar C99, que permite especificar las dimensiones de la matriz en tiempo de ejecución.

Un puntero de matriz es un tipo algo especial en C, puede apuntar a matrices completas, en lugar de solo al primer elemento de la matriz, como lo hará un puntero normal. El puntero de matriz, a diferencia de un puntero normal, conoce el tamaño de la matriz.

Un puntero de matriz se escribe como type(*name)[size] , por lo que, por ejemplo, un puntero de matriz a una matriz de 5 se escribirá como int(*arr_ptr)[5] = &the_array; .

Al acceder a los contenidos apuntados, un puntero de matriz se comporta como cualquier puntero, accede a los contenidos con * . Entonces *arr_ptr le da al conjunto señalado, y (*arr_ptr)[0] da el primer elemento de ese conjunto.

Para arreglos multidimensionales, se aplican las mismas reglas. Dado el array int arr[x][y] , un puntero de matriz a este tipo será int(*arr_ptr)[x][y] = &arr; . Accediendo a los contenidos *arr_ptr le dará una matriz bidimensional, que es equivalente a una matriz de matrices. (*arr_ptr)[0] dará por lo tanto la primera matriz en la matriz de matrices. La regla habitual para cualquier nombre de matriz cuando se usa en una expresión, es que se "descompone" en un puntero al primer elemento. Lo mismo se aplica aquí, por lo que (*arr_ptr)[0] será, por lo tanto, también lo mismo que un puntero al primer elemento en la primera matriz. Y (*arr_ptr)[0][0] dará el primer elemento de la primera matriz.

Ahora esta sintaxis (*arr_ptr)[0][0] parece un poco difícil de leer; para obtener el primer elemento de una matriz 2D, nos utilizan al escribir simplemente arr[0][0] . Entonces, al declarar el puntero de matriz, hay un truco útil. En lugar de declarar el puntero de matriz completo y correcto: int(*matrix)[x][y] , un puntero de matriz a una matriz 2D de dimensiones x * y, en su lugar, lo declaramos como int(*matrix)[y] , que es un puntero de matriz a una matriz 1D con dimensión y. Apuntará al primer elemento de la matriz 2D, que es una matriz 1D de tamaño y. Sabemos que la matriz 2D contiene x tales elementos.

Y debido a este truco, ahora podremos usar el puntero de matriz con la misma sintaxis que cuando accedemos a una matriz 2D, concretamente matrix[i][j] , en lugar de la de difícil lectura (*matrix)[i][j] .


donde está escrito double puede cambiar para su tipo de matriz

void allocMatrix(double ***matrix, int row, int col){ int i = 0; *matrix = (double **)malloc(sizeof(double *) * row); for(i = 0; i < col; i++){ *(*matrix + i) = (double *)malloc(sizeof(double) * col); } } void deallocMatrix(double **matrix, int row){ int i = 0; for(i = 0; i < row; i++){ free(matrix[i]); } free(matrix); }

cuando en main puedes usarlos así

int main(){ int i = 0, j = 0, k = 0, row = 3, col = 4; double **myMatrix = NULL; allocMatrix(&myMatrix, row, col); for(i = 0; i < row; i++){ for(j = 0; j < col; j++){ myMatrix[i][j] = k++; printf("%.0lf/t", myMatrix[i][j]); } printf("/n"); } deallocMatrix(myMatrix, row); return 0; }

salida

1 2 3 4 5 6 7 8 9 10 11 12

eso puede evitar pérdidas de memoria, pero como dijo Lundin , es mejor no usar matrices en 2d

Nunca utilice puntero a puntero para asignar matrices multidimensionales. Es una práctica extendida pero mala e incorrecta. Si lo haces, no obtendrás una verdadera matriz 2D, y generará un código más lento debido a la fragmentación del montón. También hace que el código sea más difícil de escribir, leer y mantener, lo que a su vez aumenta el potencial de pérdidas de memoria. En su lugar, asigne la matriz 2D correctamente en celdas de memoria adyacentes

[]