Definiendo un array 2D con malloc y modificándolo.

¿Cómo defino una matriz 2D usando malloc? (digamos 10X20).

Segundo, ¿puedo boost el número de filas o columnas sin crear una nueva matriz aumentada y copiar todos los datos en ella?

por ejemplo, ¿cómo asigno memoria para que la matriz sea 10×30 o 15×20?

¡gracias!

10×30:

int(*array)[30] = malloc((sizeof *array) * 10); 

15×20:

 int(*array)[20] = malloc((sizeof *array) * 15); 

Redimensionando a 20×25:

 int(*array2)[25] = realloc(array, (sizeof *array2) * 20); 

La dimensión externa (10, 15, 20) se puede determinar en tiempo de ejecución, porque no es necesaria como parte de los cálculos de índice por parte del comstackdor. La dimensión interna (30, 20, 25) debe conocerse en el momento de la comstackción. Espero eso ayude.

Tenga en cuenta que, a diferencia de las soluciones de matriz de puntero, esta puede manejarse como un único bloque de memoria, porque asigna todo en una sola porción de memoria como una matriz declarada real:

 memcpy(somewhere, array2, sizeof(int) * 20 * 25); // (sizeof *array2) * 20 

Sin embargo, en última instancia, depende de su caso de uso.


Debido a que algunas personas tienen dificultades para entender las acciones tomadas por una operación de índice a una array , vamos a ver qué nos da Clang para una expresión de índice en el siguiente código

 int main() { int(*array)[10] = malloc((sizeof *array) * 5); array[4][9] = 0; int(*array1)[10][5] = malloc((sizeof *array1) * 20); array1[19][9][4] = 0; } 

Es un buen comstackdor, que puede imprimir su AST de una manera fácil de leer

  // array[4][9] = 0; (BinaryOperator 0xba62cc0  'int' '=' (ArraySubscriptExpr 0xba62c80  'int' (ImplicitCastExpr 0xba62c60  'int *'  (ArraySubscriptExpr 0xba62c20  'int [10]' (DeclRefExpr 0xba62bdc  'int (*)[10]' Var='array' 0xba62a00) (IntegerLiteral 0xba62c00  'int' 4))) (IntegerLiteral 0xba62c40  'int' 9)) (IntegerLiteral 0xba62ca0  'int' 0)) // array1[19][9][4] = 0; (BinaryOperator 0xba630b8  'int' '=' (ArraySubscriptExpr 0xba63078  'int' (ImplicitCastExpr 0xba63058  'int *'  (ArraySubscriptExpr 0xba63018  'int [5]' (ImplicitCastExpr 0xba62ff8  'int (*)[5]'  (ArraySubscriptExpr 0xba62fa0  'int [10][5]' (DeclRefExpr 0xba62f5c  'int (*)[10][5]' Var='array1' 0xba62db0) (IntegerLiteral 0xba62f80  'int' 19))) (IntegerLiteral 0xba62fc0  'int' 9))) (IntegerLiteral 0xba63038  'int' 4)) (IntegerLiteral 0xba63098  'int' 0))) 

Tenga en cuenta que cada expresión de subíndice de matriz toma un puntero, agrega el valor del índice y genera el elemento direccionado. Si ese subelemento es una matriz, se descompone en un puntero a su primer elemento. Esto realmente no es realmente diferente a los pasos realizados para una matriz declarada

 int main() { int array[5][10] = { }; array[4][9] = 1; } 

Produce un AST muy similar, con la expresión más interior primero decayendo a un puntero a su primer elemento

  // array[4][9] = 1; (BinaryOperator 0xbf9f7e8  'int' '=' (ArraySubscriptExpr 0xbf9f7a8  'int' (ImplicitCastExpr 0xbf9f788  'int *'  (ArraySubscriptExpr 0xbf9f748  'int [10]' (ImplicitCastExpr 0xbf9f728  'int (*)[10]'  (DeclRefExpr 0xbf9f6cc  'int [5][10]' Var='array' 0xbfa81f0)) (IntegerLiteral 0xbf9f6f0  'int' 4))) (IntegerLiteral 0xbf9f768  'int' 9)) (IntegerLiteral 0xbf9f7c8  'int' 1))) 

Aunque malloc() no admite directamente matrices multidimensionales, existen soluciones alternativas, como:

 int rows = 10; int cols = 30; int *array = malloc(rows * cols * sizeof(int)); // Element (5,6) int x = 5; int y = 6; int element = array [ x * cols + y ]; 

Si bien esto no es directamente una matriz 2D, funciona, y en mi opinión es la más simple. Pero si desea utilizar la syntax [][] lugar, tendría que hacer punteros a punteros, por ejemplo:

 int rows = 10; int cols = 30; // Rows int **array = malloc(rows * sizeof(int*)); // Cols int i; for(i = 0; i < rows; i++) array[i] = malloc(cols * sizeof(int)); // Element (5,6) int x = 5; int y = 6; int element = array[x][y]; 
 // first allocate the 20 rows, that contain pointers to int // (if the matrix contains int type values) int **a = malloc(20 * sizeof(int *)); // now loop for each row and allocate data for the actual values int i; for(i = 0; i < 20; i++) { a[i] = malloc(10 * sizeof(int)); } 

Para boost el tamaño de la matriz, puede usar realloc aunque probablemente sería más fácil regenerar la matriz de diferente tamaño y copiar los valores.

En segundo lugar, ¿puedo boost el número de filas o columnas sin crear una nueva matriz aumentada y copiar todos los datos en ella?

No, no puedes cambiar el tamaño de una matriz. Lo que puedes hacer es usar punteros y realloc para hacerlo.

Una matriz 2D es una matriz 1D de matrices 1D. Como una matriz es simplemente un puntero, una matriz de matrices es una matriz de punteros. Por lo tanto, utiliza malloc para asignar una matriz de punteros (cada uno representa una columna), y luego lo usa nuevamente para asignar las matrices individuales (cada una representa una fila).

Para expandir / reducir la matriz, utilice realloc (referencia) . Aquí hay un código de ejemplo:

 #include  #include  int** alloc_matrix(int w, int h) { int** matrix; matrix = (int**) malloc(sizeof(int*) * h); for(int i = 0; i < h; i++) { matrix[i] = (int*) malloc(sizeof(int) * w); } return matrix; } void realloc_matrix(int*** matrix, int new_w, int new_h) { *matrix = (int**) realloc((void *)*matrix, sizeof(int*) * new_h); for(int i = 0; i < new_h; i++) { (*matrix)[i] = (int*) realloc((void *)(*matrix)[i], sizeof(int) * new_w); } } int main(int argc, char* argv[]) { // Allocating matrix int** m = alloc_matrix(10, 15); // Filling with some data for(int y = 0; y < 15; y++) { for(int x = 0; x < 10; x++) { m[y][x] = y * x; // Notice the index is [y][x] - NOT [x][y]! } } // Printing for(int y = 0; y < 15; y++) { for(int x = 0; x < 10; x++) { printf("%d\t", m[y][x]); // Notice the index is [y][x] - NOT [x][y]! } printf("\n"); } // Reallocating realloc_matrix(&m, 20, 10); // Filling with some data for(int y = 0; y < 10; y++) { for(int x = 0; x < 20; x++) { m[y][x] = y * x; // Notice the index is [y][x] - NOT [x][y]! } } // Printing for(int y = 0; y < 10; y++) { for(int x = 0; x < 20; x++) { printf("%d\t", m[y][x]); // Notice the index is [y][x] - NOT [x][y]! } printf("\n"); } } 

Lo siento si tengo algo mal. Mi C-fu está un poco oxidada 🙂

En lugar de usar int[row][col] , debería “envolver su matriz” en una matriz unidimensional int[row*col] .

Aquí está el código de muestra:

 #include  #include  #define DET_MALLOC_FAIL -1 #define DET_READ_FAIL -2 #define DET_WRITE_FAIL -3 typedef struct det_matrix_s { double * vect; size_t order; } det_matrix; void *det_sf_malloc(size_t dsize); det_matrix * det_matrix_new(size_t order); #define DET_MAT_ELEM(matr, i, j) \ ((matr)->vect[((matr)->order * (i)) + (j)]) int det_matrix_read(det_matrix * matr, FILE * src); int det_matrix_write(det_matrix * matr, FILE * dest); void det_matrix_delete(det_matrix * matr); /** * Malloc wrapper */ void * det_sf_malloc(size_t dsize) { void *data = malloc(dsize); if(NULL == data){ exit(DET_MALLOC_FAIL); } return (data); } /** * Allocates memory for a new matrix */ det_matrix * det_matrix_new(size_t order) { det_matrix * res = det_sf_malloc(1 * sizeof(*res)); double * vect = det_sf_malloc(order * order * sizeof(*vect)); res->order = order; res->vect = vect; return (res); } /** * Reads matrix */ int det_matrix_read(det_matrix * matr, FILE * src) { size_t i, j; if(NULL == matr || NULL == src){ return (DET_READ_FAIL); } for(i = 0; i < matr->order; ++i){ for(j = 0; j < matr->order; ++j){ if(stdin == src){ fprintf(stdout, "mat[%d][%d] = ", i, j); } fscanf(src, "%lf", &DET_MAT_ELEM(matr, i, j)); } } return (EXIT_SUCCESS); } /** * Writes matrix **/ int det_matrix_write(det_matrix * matr, FILE * dest) { size_t i, j; if(NULL == matr || NULL == dest){ return (DET_WRITE_FAIL); } for(i = 0; i < matr->order; ++i){ for(j = 0; j < matr->order; ++j){ fprintf(dest, "%5.2lf ", DET_MAT_ELEM(matr, i, j)); } fprintf(dest, "\n"); } return (EXIT_SUCCESS); } /** * Free memory for matrix */ void det_matrix_delete(det_matrix * matr) { free(matr->vect); free(matr); } /** * Main */ int main(int argc, char * argv[]) { det_matrix * mat = det_matrix_new(3); det_matrix_read(mat, stdin); det_matrix_write(mat, stdout); det_matrix_delete(mat); return (EXIT_SUCCESS); } 

Si la reasignación es un problema, pueden aparecer problemas. Y deberías usar la versión bidimensional.

Aunque esta es una vieja pregunta, aquí está mi solución diferente.

 #include  #include  #include  int main(int arvc, char* argv[]) { int (*a)[5][8]; int i, j; a = (int (*)[5][8])calloc(5*8, sizeof(int)); for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) (*a)[i][j] = i *10 + j; } for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) printf("%d ", (*a)[i][j]); printf("\n"); } return 0; } 

Comstackr y ejecutar

 [user@buzz ~]$ gcc main.c -o main [user@buzz ~]$ [user@buzz ~]$ ./main 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27 30 31 32 33 34 35 36 37 40 41 42 43 44 45 46 47 [user@buzz ~]$