Como han dicho otros, probablemente sea mejor asignar un trozo contiguo de memoria y luego averiguar la indexación usted mismo. Puede escribir una función para hacerlo si lo desea. Pero ya que parece estar interesado en saber cómo hacer frente a la malloc()
de casos múltiples, he aquí un ejemplo:
En primer lugar, definir una función free_data()
, lo que libera un int ***
con xlen
y ylen
como los dos primeros tamaños de dimensión. No necesitamos un parámetro zlen
al igual que free()
no toma la longitud del puntero que se libera.
void free_data(int ***data, size_t xlen, size_t ylen)
{
size_t i, j;
for (i=0; i < xlen; ++i) {
if (data[i] != NULL) {
for (j=0; j < ylen; ++j)
free(data[i][j]);
free(data[i]);
}
}
free(data);
}
La función de bucles sobre el puntero data
, se entera el puntero i
º int **
data[i]
. Luego, para un puntero dado int **
, lo recorre, descubriendo el j
th int *
en data[i][j]
, y lo libera. También necesita liberar data[i]
una vez que haya liberado todos data[i][j]
, y finalmente, necesita liberar data
sí mismo.
Ahora a la función de asignación. La función es un poco complicada por la comprobación de errores. En particular, dado que hay llamadas 1 + xlen + xlen*ylen
malloc
, tenemos que ser capaces de gestionar un error en cualquiera de esas llamadas, y liberar toda la memoria que hemos asignado hasta el momento. Para facilitar las cosas, confiamos en el hecho de que free(NULL)
no es operativo, por lo que establecemos todos los punteros en un nivel dado igual a NULL
antes de intentar asignarlos, de modo que si ocurre un error, podemos liberar todos los punteros.
Aparte de eso, la función es bastante simple. En primer lugar, asignar espacio para xlen
int **
valores, a continuación, para cada uno de esos xlen
punteros, asignamos espacio para ylen
int *
valores, y luego para cada uno de esos xlen*ylen
punteros, asignamos espacio para zlen
int
valores, que nos da un espacio total para xlen*ylen*zlen
int
valores:
int ***alloc_data(size_t xlen, size_t ylen, size_t zlen)
{
int ***p;
size_t i, j;
if ((p = malloc(xlen * sizeof *p)) == NULL) {
perror("malloc 1");
return NULL;
}
for (i=0; i < xlen; ++i)
p[i] = NULL;
for (i=0; i < xlen; ++i)
if ((p[i] = malloc(ylen * sizeof *p[i])) == NULL) {
perror("malloc 2");
free_data(p, xlen, ylen);
return NULL;
}
for (i=0; i < xlen; ++i)
for (j=0; j < ylen; ++j)
p[i][j] = NULL;
for (i=0; i < xlen; ++i)
for (j=0; j < ylen; ++j)
if ((p[i][j] = malloc(zlen * sizeof *p[i][j])) == NULL) {
perror("malloc 3");
free_data(p, xlen, ylen);
return NULL;
}
return p;
}
Tenga en cuenta que he simplificado malloc
llamadas un poco: en general, no se debe emitir el valor de retorno de malloc
, y especificar el objeto que se está asignando para que el operando a sizeof
operador vez de su tipo. Eso hace que malloc
llame más fácil de escribir y menos propenso a errores. Debe incluir stdlib.h
para malloc
.
Aquí es un programa de prueba usando las dos funciones anteriores:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int ***data;
size_t xlen = 10;
size_t ylen = 100;
size_t zlen = 300;
size_t i, j, k;
srand((unsigned int)time(NULL));
if ((data = alloc_data(xlen, ylen, zlen)) == NULL)
return EXIT_FAILURE;
for (i=0; i < xlen; ++i)
for (j=0; j < ylen; ++j)
for (k=0; k < zlen; ++k)
data[i][j][k] = rand();
printf("%d\n", data[1][2][1]);
free_data(data, xlen, ylen);
return EXIT_SUCCESS;
}
Por todos los medios utilizar este enfoque si le resulta más fácil usarlo. En general, esto será más lento que usar un trozo contiguo de memoria, pero si encuentra que la velocidad está bien con el esquema anterior, y si le hace la vida más fácil, puede seguir usándolo. Incluso si no lo usa, es bueno saber cómo hacer que ese esquema funcione.
añadir #include y retire el * de * array [i] y se ejecutará cuando se compila en gcc –
Paul
también soy curioso sobre cómo implementar esto. La solución de matriz 1D es "más limpia" (la que uso hasta ahora), sin embargo, para el cálculo numérico es significativamente más lenta que la 3D asignada estáticamente, debido al cálculo de "compensación". – lmount
@WorldCitizeN ¿ha medido realmente este rendimiento? Cuando accede a una matriz estáticamente asignada, se ejecutan los mismos cálculos. La única diferencia es que no los escribes. – charliehorse55