Определение многомерного массива как массива массивов массивов очень удобно, потому что вы можете обращаться к элементам с привычной нотацией p[i][j][k]
вместо выполнения арифметики индекса.Однако другие уже отмечали, что это менее эффективно, чем выделение всего массива в виде большого чанка.
Вы можете получить лучшее из обоих миров с помощью следующего трюка: выделить массив из dim_len[0]
указателей намассив dim_len[0]*dim_len[1]
указателей на массив dim_len[0]*dim_len[1]*dim_len[2]
ячеек данных.Таким образом, у вас есть только три выделения (столько же, сколько измерений), и вы все равно можете использовать простую нотацию p[i][j][k]
, при условии, что промежуточные массивы указателей правильно инициализированы.И вы также можете выполнять индексную арифметику на **p
по вашему выбору.
Вот моя версия вашей программы, использующая этот трюк:
/*
* Allocation of multidimensional arrays.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
/*
* Allocate a multidimensional array of unsigned chars.
* Cast the returned pointer to (unsigned char **...*)
*/
void *mm(const int dim_len[])
{
int i, j, size, nmemb = 1, prev_nmemb;
void *p = NULL, *q = NULL;
void **prev_q;
for (i = 0; dim_len[i]; i++) {
prev_nmemb = nmemb;
nmemb *= dim_len[i];
size = dim_len[i+1] ? sizeof(void *) : sizeof(unsigned char);
prev_q = q;
q = malloc(nmemb * size);
if (i == 0) p = q;
else for (j = 0; j < prev_nmemb; j++)
prev_q[j] = q + j * dim_len[i] * size;
}
return p;
}
/* Free the multidimensional array */
void ff(void *p, int dimensions)
{
int i;
void **q;
for (i = 0; i < dimensions; i++) {
q = *((void **) p);
free(p);
p = q;
}
}
int main(void)
{
const int dims[4] = {8832, 256, 64, 0};
unsigned char ***p;
int i, j, k;
printf("Allocating memory.\n");
p = mm(dims);
printf("Filling the array.\n");
for (i = 0; i < dims[0]; i++)
for (j = 0; j < dims[1]; j++)
for (k = 0; k < dims[2]; k++)
p[i][j][k] = (i + 3*j + 5*k) % 256;
printf("Checking contents.\n");
for (i = 0; i < dims[0]; i++)
for (j = 0; j < dims[1]; j++)
for (k = 0; k < dims[2]; k++)
assert(p[i][j][k] == (i + 3*j + 5*k) % 256);
printf("Waiting 10 seconds.\n");
sleep(10);
printf("Freeing memory.\n");
ff(p, 3);
printf("Waiting 10 seconds.\n");
sleep(10);
return 0;
}
Мои тесты показывают, что когда я освобождаюмногомерный массив, память фактически возвращается в ОС.Вот вывод ps
непосредственно перед и сразу после освобождения:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
edgar 5201 73.0 3.7 151852 150556 pts/0 S+ 14:11 0:00 ./test
edgar 5201 6.1 0.0 1668 408 pts/0 S+ 14:11 0:00 ./test