如何在C中分配和声明结构数组的3D?

时间:2015-02-22 02:42:20

标签: c arrays struct typedef allocation

如何在C中分配和声明结构的3D数组? 你首先分配数组还是声明它? 我觉得你必须先分配它,这样你就可以声明它在堆上了,但那么你如何分配尚未制作的东西呢? 另外,您应该一次性还是逐个元素地分配它? 我也正确地将结构放入数组中? 我对如何做的猜测是:

header.h

struct myStruct{
   int a;
   int b;
}; 
typedef struct myStruct myStruct_t;

的main.c

#include "header.h"
#include <stdio.h>
#include <stdlib.h>
int main(void){

    int length=2;
    int height=3;
    int width =4;
    myStruct_t *elements;
    struct myStruct arr = (*myStruct_t) calloc(length*height*width, sizeof(myStruct);
    //zero based array
    arr[length-1][height-1][width-1];

    int x=0;
    while(x<length){
        int y=0;
        while(y<height){
            int z=0;
            while(z<depth){
                arr[x][y][z].a=rand();
                arr[x][y][z].b=rand();
                z++;
            }
            y++;
        }
        x++;
    }
    return 0;
}    

2 个答案:

答案 0 :(得分:1)

根据您的需要,有几种不同的方法可以做到这一点。首先,您可以在堆栈上分配您的数组(在C99和一些编译器中),如下所示:

myStruct_t arr[length][height][depth];

如果您希望在堆上分配它,那么您可以执行适当大小的单个分配。然后,您可以自己进行索引计算,也可以使指针为您完成工作(在C99和一些编译器中):

void *buf = malloc(length * height * width * sizeof(myStruct_t));
myStruct_t *arr = buf;
myStruct_t (*arr2)[height][width] = buf;

/* TODO: check return of malloc */
...

arr[x * height * width + y * width + z].a = rand();  /* indexing the C89 way */
arr2[x][y][z].b = rand();                            /* indexing the C99 way */

或者您可以手动分配多个维度。

#include <stddef.h>
#include <stdlib.h>

typedef struct myStruct
{
  int a, b;

} myStruct_t;

int main()
{
  myStruct_t ***arr;
  int length = 5000, height = 1000, depth = 20;
  int x, y, z;
  int ret = 1;

  if (NULL == (arr = malloc(length * sizeof(myStruct_t**))))
    goto FAIL;

  for (x = 0; x < length; ++x)
  {
    if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*))))
      goto FAIL_X;

    for (y = 0; y < height; ++y)
    {
      if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t))))
        goto FAIL_Y;

      for (z = 0; z < depth; ++z)
      {
        arr[x][y][z].a = rand();
        arr[x][y][z].b = rand();
      }
    }
  }

  /* TODO: rest of program logic */

  /* program successfully completed */

  ret = 0;

  /* reclaim arr */

FAIL_CLEANUP: /* label used by TODO code that fails */

  for (x = length - 1; x >= 0; --x)
  {
    for (y = height - 1; y >= 0; --y)
    {
      free(arr[x][y]);
    FAIL_Y:
      ;
    }

    free(arr[x]);
  FAIL_X:
    ;
  }

  free(arr);

FAIL:    
  return ret;
}

这最后一个版本为它包含的所有显式指针使用了更多的内存,它的内存位置更差,并且正确分配和回收它要复杂得多。但是,它确实允许您的尺寸不同的尺寸。例如,如果您需要,数组arr[0][4]的大小可以与arr[0][7]不同。

如果要在堆上分配它,那么您可能希望第二个版本具有单个分配和多维指针(如果可用),或者使用适当的数学手动自己编制索引。

答案 1 :(得分:1)

简单的方法是:

 myStruct_t (*arr2)[height][width] = calloc( length * sizeof *arr );

然后您的循环可以访问arr2[x][y][z].a = rand();,依此类推。如果您不熟悉这种调用callocsee here的方式。像往常一样使用malloc,在继续之前检查arr2NULL

三指针方法实际上并不是一个实用的解决方案。如果编译器不支持可变修改类型,则应将数组展平为1-D。