Realmente no entiendo algunas cosas básicas en C, como la asignación dinámica de matrices. Sé que puedes hacer:
int **m;
para declarar una matriz bidimensional (que posteriormente se asignaría utilizando alguna función * alloc). También se puede acceder “fácilmente” haciendo *(*(m + line) + column). Pero, ¿cómo debo asignar un valor a un elemento de esa matriz? Usando gcc la siguiente declaración m[line][column] = 12; falla con una falla de segmentación.
Cualquier artículo/docs será apreciado. 🙂
Esto no es una “matriz de matrices”.
– demasiado honesto para este sitio
24 de junio de 2016 a las 14:27
jpalecek
los m[line][column] = 12 la sintaxis está bien (siempre y cuando line y column están dentro del rango).
Sin embargo, no escribió el código que usa para asignarlo, por lo que es difícil determinar si es incorrecto o correcto. Debe ser algo a lo largo de las líneas de
m = (int**)malloc(nlines * sizeof(int*));
for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));
Algunas notas al margen:
De esta manera, puede asignar cada línea con una longitud diferente (por ejemplo, una matriz triangular)
Puede reasignar () o liberar () una línea individual más tarde mientras usa la matriz
Debe liberar () cada línea, cuando libera () toda la matriz
@jpalecek: la forma en que asigné memoria para eso fue: m = malloc (líneas * columnas * tamaño de (int *));
– hiperbóreo
18 de enero de 2009 a las 21:55
@hyperboreean: Eso asignaría una matriz unidimensional de punteros. Lo que desea es una matriz de punteros que cada uno apunte a otra matriz. Primero debe asignar la matriz de punteros, luego asignar memoria para cada matriz a la que se apunta.
– Paige Ruten
18 de enero de 2009 a las 22:03
Wow, dos ediciones patéticamente inútiles. @chakrit: lanzar malloc generalmente se considera una mala práctica en C, ya que no es necesario y puede enmascarar errores. +1 por la respuesta original.
– Roberto Gamble
18 de enero de 2009 a las 22:24
@Robert, desafortunadamente depende de la implementación del compilador. Algunos compiladores más antiguos tienen mallocs no estándar que requieren una conversión. VisualStudio fue así hasta hace poco (no recuerdo la versión exacta)
– JaredPar
18 de enero de 2009 a las 22:48
Convertir malloc es una buena práctica en C++ porque es necesario si la variable en el LHS no es un puntero vacío. Es una mala práctica en C porque las advertencias que elimina casi siempre son errores que deben abordarse adecuadamente y eliminar la advertencia solo trata el síntoma.
– Roberto Gamble
19 de enero de 2009 a las 0:47
Tu sintaxis m[line][colummn] es correcto. Pero para usar una matriz 2D en C, debe asignarle memoria. Por ejemplo, este código asignará memoria para una tabla de línea y columna dadas.
int** AllocateArray(int line, int column) {
int** pArray = (int**)malloc(line*sizeof(int*));
for ( int i = 0; i < line; i++ ) {
pArray[i] = (int*)malloc(column*sizeof(int));
}
return pArray;
}
Tenga en cuenta que omití las comprobaciones de error de malloc por brevedad. Una solución real debería incluirlos.
Hay varias formas de crear dinámicamente “matrices multidimensionales” en C con diferencias sutiles pero importantes, consulte c-faq.com/aryptr/dynmuldimary.html para detalles. Además, como advertencia para los demás sobre los peligros de lanzar malloc: c-faq.com/malloc/mallocnocast.html.
– Roberto Gamble
19 de enero de 2009 a las 6:01
No es una matriz 2d, es una matriz de matrices, por lo que necesita múltiples asignaciones.
Probablemente este fue mi problema de que estaba recibiendo una falla de segmentación.
– hiperbóreo
18 de enero de 2009 a las 22:02
Cristóbal
Aquí hay una versión modificada de la solución de quinmars que solo asigna un bloque de memoria y se puede usar con valores genéricos por cortesía de void *:
No estoy seguro de si es realmente seguro lanzar void ** para int ** (Creo que el estándar permite que se realicen conversiones al convertir a/desde void * ?), pero funciona en gcc. Para estar seguro, debe reemplazar cada ocurrencia de void * con int * …
Las siguientes macros implementan una versión con seguridad de tipos del algoritmo anterior:
int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;
Aunque estoy de acuerdo con las otras respuestas, en la mayoría de los casos es mejor asignar toda la matriz a la vez, porque malloc es bastante lento.
int **
array_new(size_t rows, size_t cols)
{
int **array2d, **end, **cur;
int *array;
cur = array2d = malloc(rows * sizeof(int *));
if (!array2d)
return NULL;
array = malloc(rows * cols * sizeof(int));
if (!array)
{
free(array2d);
return NULL;
}
end = array2d + rows;
while (cur != end)
{
*cur = array;
array += cols;
cur++;
}
return array2d;
}
Para liberar la matriz simplemente haga: free(*array); free(array);
Nota: esta solución solo funciona si no desea cambiar el orden de las filas, ya que podría perder la dirección del primer elemento, que necesita para liberar la matriz más adelante.
Esa es una solución ingeniosa 🙂 Aunque si quisiera asignarlo de una vez, probablemente recurriría a la “matriz[i*cols+j]” direccionar y deshacerse de la matriz “array2d”.
– jpalecek
18 de enero de 2009 a las 23:39
EvilTeach
Humm. ¿Qué tal el humo antiguo y los espejos como opción?
#define ROWS 5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))
int main(void)
{
int *p = (int *) malloc (ROWS * COLS * sizeof(int));
if (p != NULL)
{
size_t r;
size_t c;
for (r = 0; r < ROWS; r++)
{
for (c = 0; c < COLS; c++)
{
X(r,c) = r * c; /* put some silly value in that position */
}
}
/* Then show the contents of the array */
for (r = 0; r < ROWS; r++)
{
printf("%d ", r); /* Show the row number */
for (c = 0; c < COLS; c++)
{
printf("%d", X(r,c));
}
printf("\n");
}
free(p);
}
else
{
/* issue some silly error message */
}
return 0;
}
Esa es una solución ingeniosa 🙂 Aunque si quisiera asignarlo de una vez, probablemente recurriría a la “matriz[i*cols+j]” direccionar y deshacerse de la matriz “array2d”.
– jpalecek
18 de enero de 2009 a las 23:39
Keltia
Utilizando malloc(3) para asignar la primera matriz y poner allí punteros creados por malloc(3) debería trabajar con array[r][c] porque debe ser equivalente a *(*(array + r) + c)está en el estándar C.
¿Ha sido útil esta solución?
Tu feedback nos ayuda a saber si la solución es correcta y está funcionando. De esta manera podemos revisar y corregir el contenido.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
Esto no es una “matriz de matrices”.
– demasiado honesto para este sitio
24 de junio de 2016 a las 14:27