正如其他人所说,最好分配一块连续的内存,然后自己找出索引。如果需要,您可以编写一个函数来执行此操作。但是由于您似乎有兴趣知道如何处理多个malloc() 案例,因此这里有一个示例:
首先,我定义了一个函数free_data(),它以xlen 和ylen 作为前两个维度大小来释放int ***。我们不需要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,找到ith int ** 指针data[i]。然后,对于给定的int ** 指针,它循环遍历它,找出data[i][j] 中的jth int *,并释放它。它还需要在释放所有data[i][j] 后释放data[i],最后,它需要释放data 本身。
现在到分配函数。该功能通过错误检查有点复杂。特别是,由于有 1 + xlen + xlen*ylen malloc 调用,我们必须能够处理任何这些调用中的失败,并释放我们迄今为止分配的所有内存。为了让事情变得更简单,我们依靠free(NULL) 是无操作的事实,所以我们在尝试分配它们之前将所有指针设置为等于NULL 的给定级别,这样如果发生错误,我们可以释放所有指针。
除此之外,功能很简单。我们首先为xlenint ** 值分配空间,然后为每个xlen 指针分配空间给ylenint * 值,然后为每个xlen*ylen 指针分配空间zlenint 值,为我们提供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 调用更容易编写并且更不容易出错。您需要为malloc 包含stdlib.h。
这是一个使用以上两个函数的测试程序:
#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;
}
如果您发现这种方法更容易使用,请务必使用它。一般来说,这会比使用一块连续的内存要慢,但是如果你发现上面的方案速度还可以,如果它让你的生活更轻松,你可以继续使用它。即使您不使用它,也很高兴知道如何使这样的方案起作用。