Malloc是C中的三维数组?

Mik*_*ike 28 c arrays multidimensional-array

我正在将一些MATLAB代码翻译成C,我正在转换的脚本大量使用具有10*100*300复杂条目的3D数组.数组的大小也取决于传感器的输入,理想情况下应该动态分配数组.到目前为止,我已经尝试了两种方法,第一种方法是平面1D阵列

value = array[x + (y*xSize) + (z*ySize*xSize)]
Run Code Online (Sandbox Code Playgroud)

哪会伤害我的大脑使用.我还尝试了一个指针数组的数组

int main () {
  int ***array = malloc(3*sizeof(int**));
  int i, j;

  for (i = 0; i < 3; i++) {
    *array[i] = malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      array[i][j] = malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试分配数据时,会出现seg错误.

在一个完美的世界中,我想使用第二种方法和数组符号来实现更清晰,更简单的编程.有没有更好的方法在C中动态分配三维数组?

tim*_*tes 18

我会选择第一个选项(单个1D阵列),因为它会为你提供一个单独的内存块,而不是潜在的数千个碎片内存块

如果访问数组的正确元素正在努力,我会写一个实用工具方法将x,y,z位置转换为1D数组的偏移量

int offset(int x, int y, int z) { 
    return (z * xSize * ySize) + (y * xSize) + x; 
}
Run Code Online (Sandbox Code Playgroud)


Alo*_*hal 9

正如其他人所说,最好分配一个连续的内存块,然后自己弄清楚索引.如果需要,您可以编写一个函数来执行此操作.但是既然你似乎对知道如何处理多个malloc()案例感兴趣,这里有一个例子:

首先,我定义一个函数free_data(),它释放一个int ***with xlenylen作为前两个维度大小.我们不需要一个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);
}
Run Code Online (Sandbox Code Playgroud)

该函数遍历指针data,找出iint **指针data[i].那么,对于一个给定的int **指针,它遍历它,找出jint *data[i][j],并释放它.它还需要释放data[i]一旦它释放所有data[i][j],最后,它需要释放data自己.

现在来分配功能.错误检查功能有点复杂.特别是,由于存在1 + xlen + xlen*ylen malloc调用,我们必须能够处理任何这些调用中的失败,并释放到目前为止我们分配的所有内存.为了简化操作,我们依赖于free(NULL)no-op 这一事实,因此我们将所有指针设置在给定级别,等于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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我已经简化了malloc调用:通常,您不应该转换返回值malloc,并将您要分配的对象指定为操作sizeof符而不是其类型.这使得malloc调用编写更简单,更不容易出错.您需要包括stdlib.hmalloc.

这是一个使用以上两个函数的测试程序:

#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;
}
Run Code Online (Sandbox Code Playgroud)

如果您发现它更容易使用,请务必使用此方法.一般来说,这比使用连续的大块内存要慢,但是如果你发现上述方案的速度没问题,并且如果它让你的生活更轻松,你可以继续使用它.即使您不使用它,也很高兴知道如何使这样的方案工作.


Dim*_*ims 8

你确定需要使用malloc吗?C允许本地创建多维数组:

int a2[57][13][7];
Run Code Online (Sandbox Code Playgroud)

或者您可以通过malloc以下方式使用:

int (*a)[13][7]; // imitates 3d array with unset 3rd dimension
                 // actually it is a pointer to 2d arrays

a = malloc(57 * sizeof *a);    // allocates 57 rows

a[35][7][3] = 12; // accessing element is conventional

free(a); // freeing memory
Run Code Online (Sandbox Code Playgroud)


Joh*_*itb 7

C89中没有办法做你想做的事情,因为C中的数组类型只能用编译时已知值指定.因此,为了避免疯狂的动态分配,你必须坚持一维方式.您可以使用一个功能来简化此过程

int index(int x, int y, int z) {
  return x + (y*xSize) + (z*ySize*xSize);
}

int value = array[index(a, b, c)];
Run Code Online (Sandbox Code Playgroud)

在C99中,即使维度是运行时值,也可以使用普通的数组语法:

int (*array)[X][Y][Z] = (int(*)[X][Y][Z])malloc(sizeof *p); 
// fill...
int value = (*array)[a][b][c];
Run Code Online (Sandbox Code Playgroud)

但是,它仅适用于本地非静态数组.


And*_*Dog 6

哦,我讨厌malloc数组分配^^

这是一个正确的版本,基本上它只是一个不正确的行:

int main () {
  int ***array = (int***)malloc(3*sizeof(int**));
  int i, j;

  for (i = 0; i < 3; i++) {
    // Assign to array[i], not *array[i] (that would dereference an uninitialized pointer)
    array[i] = (int**)malloc(3*sizeof(int*));
    for (j = 0; j < 3; j++) {
      array[i][j] = (int*)malloc(3*sizeof(int));
    }
  }

  array[1][2][1] = 10;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 您不需要转换malloc返回的指针. (2认同)