
claudio
¿Hay alguna forma de hacer malloc una matriz grande, pero referirse a ella con sintaxis 2D? quiero algo como:
int *memory = (int *)malloc(sizeof(int)*400*200);
int MAGICVAR = ...;
MAGICVAR[20][10] = 3; //sets the (200*20 + 10)th element
ACTUALIZACIÓN: Es importante mencionar esto: solo quiero tener un bloque de memoria contiguo. Simplemente no quiero escribir una macro como:
#define INDX(a,b) (a*200+b);
y luego referirse a mi blob como:
memory[INDX(a,b)];
Preferiría mucho:
memory[a][b];
ACTUALIZACIÓN: Entiendo que el compilador no tiene forma de saber tal cual. Estaría dispuesto a proporcionar información adicional, algo como:
int *MAGICVAR[][200] = memory;
¿No existe una sintaxis como esta? Tenga en cuenta que la razón por la que no solo uso una matriz de ancho fijo es que es demasiado grande para colocarla en la pila.
ACTUALIZACIÓN: OK chicos, puedo hacer esto:
void toldyou(char MAGICVAR[][286][5]) {
//use MAGICVAR
}
//from another function:
char *memory = (char *)malloc(sizeof(char)*1820*286*5);
fool(memory);
Recibo una advertencia, passing arg 1 of toldyou from incompatible pointer type
, pero el código funciona y he verificado que se accede a las mismas ubicaciones. ¿Hay alguna manera de hacer esto sin usar otra función?
En la misma línea que la respuesta de Cogwheel, aquí hay un truco (algo sucio) que hace solo una llamada a malloc()
:
#define ROWS 400
#define COLS 200
int** array = malloc(ROWS * sizeof(int*) + ROWS * COLS * sizeof(int));
int i;
for (i = 0; i < ROWS; ++i)
array[i] = (int*)(array + ROWS) + (i * COLS);
Esto llena la primera parte del búfer con punteros a cada fila en los datos de matriz contiguos inmediatamente siguientes.

tim schaeffer
Utilice un puntero a las matrices:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int (*arr)[10];
arr = malloc(10*10*sizeof(int));
for (int i = 0; i < 10; i++)
for(int j = 0; j < 10; j++)
arr[i][j] = i*j;
for (int i = 0; i < 10; i++)
for(int j = 0; j < 10; j++)
printf("%d\n", arr[i][j]);
free(arr);
return 0;
}
#define ROWS 400
#define index_array_2d(a,i,j) (a)[(i)*ROWS + (j)]
...
index_array_2d( memory, 20, 10 ) = -1;
int x = index_array_2d( memory, 20, 10 );
Editar:
Matrices y punteros Mira muy parecidos, pero el compilador los trata de manera muy diferente. Veamos qué se debe hacer para indexar una matriz y eliminar la referencia de un puntero con desplazamiento:
-
Digamos que declaramos una matriz estática (la matriz en la pila es solo un poco más complicada, el desplazamiento fijo de un registro, pero esencialmente lo mismo):
static int array[10];
-
Y un puntero:
static int* pointer;
-
Luego eliminamos la deferencia de cada uno de la siguiente manera:
x = array[i];
x = pointer[i];
Lo que hay que tener en cuenta es que la dirección del comienzo de array
así como, dirección de pointer
(no su contenido) son reparado en el momento del enlace/carga. Luego, el compilador hace lo siguiente:
- Para
array
desreferenciar:
- carga el valor de
i
,
- se suma al valor de
array
es decir, su dirección fija, para formar la dirección de memoria de destino,
- carga el valor de la dirección calculada
- Para
pointer
desreferenciar:
- carga el valor de
i
,
- carga el valor de
pointer
es decir, el contenido en su dirección,
- suma dos valores para formar la dirección efectiva
- carga el valor de la dirección calculada.
Lo mismo sucede con la matriz 2D con pasos adicionales para cargar el segundo índice y multiplicarlo por el tamaño de la fila (que es una constante). Todo esto se decide en tiempo de compilación, y no hay forma de sustituir uno por otro en tiempo de ejecución.
Editar:
@caf aquí tiene la solución correcta. Después de todo, hay una forma legal dentro del lenguaje de indexar un puntero como una matriz bidimensional.
El compilador y el tiempo de ejecución no tienen forma de conocer las capacidades de dimensión previstas con solo una multiplicación en la llamada malloc.
Debe usar un puntero doble para lograr la capacidad de dos índices. Algo como esto debería hacerlo:
#define ROWS 400
#define COLS 200
int **memory = malloc(ROWS * sizeof(*memory));
int i;
for (i = 0; i < ROWS; ++i)
{
memory[i] = malloc(COLS * sizeof(*memory[i]);
}
memory[20][10] = 3;
Asegúrese de verificar todos los valores de retorno de su malloc para obtener retornos NULL, lo que indica una falla en la asignación de memoria.
Sí, esto ya se ha tratado muchas veces en SO, por ejemplo, Programación en C: malloc() para una matriz 2D (usando puntero a puntero)
– Pablo R.
29 de junio de 2010 a las 19:47
er lo siento, debo decir que no quiero tener punteros anidados. solo quiero un bloque contiguo de memoria.
– claudio
29 de junio de 2010 a las 19:49
Después de publicar mi respuesta, tenía la idea de “te dije” dando vueltas en mi cabeza. Simplemente no puedo imaginar cómo este poco de azúcar sintáctico vale todos los aros por los que tienes que pasar para conseguirlo;)
– Rueda dentada
29 de junio de 2010 a las 20:48
@Cogwheel: je, supongo que no lo es, ¡pero no lo sabía cuando publiqué esta pregunta por primera vez!
– claudio
29 de junio de 2010 a las 20:58