C - 创建整数的3D数组并将其初始化为零

时间:2018-05-06 18:12:32

标签: c multidimensional-array

我试图创建一个初始化为零的整数的3D数组,每个固定大小表示为" dim"。

例如,对于dim = 3,它将有27个单元用于整数。

我试过了:

int ***board;
int **rows;
int *tried;
board = calloc(dim,sizeof(int**));
rows = calloc(dim*dim, sizeof(int*));
tried = calloc(dim*dim*dim, sizeof(int));
int i;
int j;
int k;
for (i=0 ; i<dim ; i++) {
    board[i] = rows + i*dim*dim;
    for (j=0 ; j<dim ; j++) {
        board[i][j] = tried + j*dim + i*dim*dim;
        }
}
for (i=0 ; i<dim ; i++) {
    for (j=0 ; j<dim ; j++) {
        for (k=0 ; k<dim ; k++) {
            board[i][j][k] = 0;
        }
    }
}

尝试调试它,我发现它可以工作,直到:

board[1][1][0] = 0

然后程序卡住了,我无法找到原因。

有人可以解释一下吗?

谢谢!

3 个答案:

答案 0 :(得分:4)

首先是关于代码中的错误。比较一下:

rows = calloc(dim*dim, sizeof(int*));

到此:

for (i=0 ; i<dim ; i++) {
    board[i] = rows + i*dim*dim;

分配给rows的数组的整个大小为dim*dim个元素。因此,已经在此循环的第二次迭代中,您可以访问它越界。你可能意味着:

for (i=0 ; i<dim ; i++) {
    board[i] = rows + i*dim;

正如我在评论中已经提到的,这是 3D阵列。它通过使用指针来模仿代码中的用法,并且您在这里使用了一种聪明的技巧,因此您总共只需要3次分配。在以下条件下这可能是一个好主意:

  • 您的dim在运行时是可变的,因此您无法事先知道,
  • 您必须为不支持VLA 1)(可变长度数组)的编译器编写代码。

如果其中一个条件不成立,使用真正的3D阵列要好得多。如果在离开您的功能后阵列不必存在并且尺寸不是巨大,那么只需使用具有自动存储持续时间的简单变量,例如

int board[3][3][3] = { 0 }; // possibly #define the dimension

或者,对于变量dim,需要支持VLAs的编译器

int board[dim][dim][dim] = { 0 };

另一方面,如果数组很大并且/或者你需要从函数返回它,你确实必须动态分配它。然后使用以下内容:

int (*board)[3][3] = calloc(3, sizeof *board); // static size
int (*board)[dim][dim] = calloc(dim, sizeof *board); // dynamic case, with VLA suppport

另请注意,calloc()已将已分配的内存设置为0,因此无需遍历整个内存。

附注:

  • sizeof,更喜欢表达形式,所以不要写

    int *a = calloc(5, sizeof(int));
    

    更好写

    int *a = calloc(5, sizeof *a);
    

    这可以避免以后更改a类型时的错误。

  • 始终检查malloc()和朋友的返回值 - 他们可能会返回空指针(例如,当您的内存不足时)。

1) VLA不存在于最早的标准C89 / C90中 - 它们作为强制性特征在C99中引入,但后来在C11中被选择。这允许C11编译器省略它们,这在例如时可能是有意义的。针对嵌入式系统。实际上,如果不是特殊目的,您可以安全地假设符合C11的编译器支持它们。

答案 1 :(得分:0)

我重写了你的代码,以显示3D数组的分配情况。正如评论中指出的那样,由于calloc为你做了这个,所以不需要将数组初始化为0。如果你使用malloc,数组就不会被初始化。

_GScene(QGraphicsScene)

你想要存储的内容取决于你,在我的例子中,我写了每个索引的计数器总和。

答案 2 :(得分:0)

以下代码为Unlicense。

我会建议一些不同的东西。只需创建一维数组并设置一些边界即可将其解释为3D。我为您添加了一些测试用例,以便更好地了解它的工作原理。别忘了看看calloc&#39;打电话是。这是代码:

#include <stdlib.h>
#include <stdio.h>

int getindex(int dim, int x, int y, int z) {
  return z * dim * dim + y * dim + x;
}

void printarray(int* tdarray, int dim) {
  printf("[\n");
    for (int i = 0; i < dim; i++) {
      printf("\t[\n");
      for (int j = 0; j < dim; j++) {   
      printf("\t\t[");
      for (int k = 0; k < dim; k++) {
        if (k == 0) printf("%d", *(tdarray + getindex(dim, k, j, i)));
        else printf(",\t %d", *(tdarray + getindex(dim, k, j, i)));
      } 
      printf("]\n");
    }
    printf("\n\t]\n");
  }
  printf("]\n");
}

int main() {
  int dim = 10;
  size_t arraysize = sizeof (int) * dim * dim * dim;

  int lookupindex = getindex(dim, 7, 5, 4); /* Numbers picked randomly */

  int* tdarray = (int*) malloc(arraysize);

  calloc(*tdarray, arraysize);

  /* Below is test code and visualizations, all magic happens above.*/

  if (*(tdarray + lookupindex) == 0) *(tdarray + lookupindex) = 7;

  printf("tdarray[x:%d, y:%d, z:%d]:\t%d\n\n", 7, 5, 4, *(tdarray + lookupindex));

  printarray(tdarray, dim);

  printf("\n\n\n\n\n\n\n\n\n\n");

  for (int i = 0; i < getindex(dim, 9, 9, 9) + 1; i++) *(tdarray + i) = i;

  printarray(tdarray, dim);

  free(tdarray);
}