Как уже говорили другие, вероятно, лучше выделить один непрерывный фрагмент памяти, а затем самостоятельно разобраться с индексацией. Вы можете написать функцию для этого, если хотите. Но поскольку вам, кажется, интересно узнать, как поступить с множественным случаем malloc()
, вот пример:
Во-первых, я определяю функцию free_data()
, которая освобождает int ***
с xlen
и ylen
в качестве первых двух размеров измерения. Нам не нужен параметр zlen
, так же как free()
не принимает длину освобождаемого указателя.
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);
}
Функция перебирает указатель data
, находит i
th int **
указатель data[i]
. Затем для заданного указателя int **
он перебирает его, находит j
th int *
в data[i][j]
и освобождает его. Ему также нужно освободить data[i]
после того, как он освободит все data[i][j]
, и, наконец, ему нужно освободить самого data
.
Теперь о функции распределения. Функция немного усложнена проверкой ошибок. В частности, поскольку существует 1 + xlen + xlen*ylen
malloc
вызовов, мы должны быть в состоянии обработать сбой в любом из этих вызовов и освободить всю выделенную до сих пор память. Чтобы упростить задачу, мы полагаемся на тот факт, что free(NULL)
не используется, поэтому мы устанавливаем все указатели на заданном уровне равными NULL
, прежде чем пытаться их выделить, чтобы в случае ошибки мы могли освободить все указатели. указатели.
В остальном функция достаточно проста. Сначала мы выделяем место для xlen
int **
значений, затем для каждого из этих xlen
указателей мы выделяем место для ylen
int *
значений, а затем для каждого из этих xlen*ylen
указателей мы выделяем место для zlen
int
значений, что дает нам общее пространство для xlen*ylen*zlen
int
ценности:
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;
}
Обратите внимание, что я немного упростил вызовы malloc
: в общем, вы не должны приводить возвращаемое значение malloc
и указывать объект, для которого вы выделяете, в качестве операнда для оператора sizeof
вместо его типа. Это делает вызовы malloc
более простыми в написании и менее подверженными ошибкам. Вам нужно включить stdlib.h
для malloc
.
Вот тестовая программа, использующая две вышеупомянутые функции:
#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;
}
Во что бы то ни стало, используйте этот подход, если вам проще его использовать. В целом, это будет медленнее, чем использование непрерывного блока памяти, но если вы обнаружите, что скорость соответствует приведенной выше схеме, и если это облегчает вашу жизнь, вы можете продолжать использовать ее. Даже если вы ей не пользуетесь, приятно знать, как заставить такую схему работать.
person
Alok Singhal
schedule
21.02.2010