如何将分配的数组(运行时已知的大小)放入结构中?

问题描述 投票:0回答:2

为了在编译时处理大小未知的 3D 数组,我编写了以下有效的程序:

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

typedef struct {
  int x,y,z;
} dim3D_t;

void print_array(dim3D_t *dim3D, int (*my_array)[dim3D->y][dim3D->z]) {
  for (int i_x=0; i_x<dim3D->x; i_x++)
    for (int i_y=0; i_y<dim3D->y; i_y++)
      for (int i_z=0; i_z<dim3D->z; i_z++)
        printf("%d %d %d : %d\n",i_x,i_y,i_z,my_array[i_x][i_y][i_z]);
}

void alloc_and_init_array(dim3D_t *dim3D, int (**my_array)[dim3D->y][dim3D->z]) {

  *my_array = malloc( sizeof(int) * dim3D->x * dim3D->y * dim3D->z );
  for (int i_x=0; i_x<dim3D->x; i_x++)
    for (int i_y=0; i_y<dim3D->y; i_y++)
      for (int i_z=0; i_z<dim3D->z; i_z++)
        (*my_array)[i_x][i_y][i_z]=100*i_x+10*i_y+i_z;
}

int main() {
  dim3D_t dim3D;
  int (*my_array)[dim3D.y][dim3D.z];
  
  scanf("%d %d %d", &dim3D.x, &dim3D.y, &dim3D.z);  
  alloc_and_init_array(&dim3D, &my_array);
        
  print_array(&dim3D, my_array);
}

我发现使用像

my_array[][][]
这样的语法访问数组元素非常方便,并且只分配一个内存块。

但是,现在,我希望将数组作为结构中的成员。我怎样才能做到这一点?

我想避免一维数组(即在结构成员中添加

int *array
并使用
my_struct.my_array[i_x*dim3D.y*dim3D.z+i_y*din3D.z+i_z]
访问元素)或拥有许多内存块(int **、int * 数组)。

arrays c struct malloc
2个回答
0
投票

灵活数组成员仅适用于一维。然而,将它们转换为数组指针或从它们转换为数组指针是安全的,因为对于 C 类型系统而言,变量是通过

int
类型的左值访问的。在这里使用灵活的数组成员有点麻烦,因为您需要进行强制转换。但很有可能。

修改后的程序,并在评论中进行一些解释:

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

typedef struct {
  size_t x,y,z;
  int array[];
} dim3D_t;

// the function gets a little bit more readable with a struct:
void alloc_and_init_array (dim3D_t** dim3D, size_t x, size_t y, size_t z) {

  // watch out for people using sizeof *dim3D style here:
  *dim3D = malloc( sizeof(dim3D_t) + sizeof(int[x][y][z]) );
  if(*dim3D==NULL) { /* TODO error handling */ }

  (*dim3D)->x = x;
  (*dim3D)->y = y;
  (*dim3D)->z = z;

  // cast from the flexible array to an array pointer type with same element type:
  int (*arrptr)[y][z] = (int(*)[y][z]) (*dim3D)->array;

  for(size_t i=0; i<x; i++)
    for(size_t j=0; j<y; j++)
      for(size_t k=0; k<z; k++)
        arrptr[i][j][k] = 100*i + 10*j + k;
}

void print_array (const dim3D_t* dim3D) { // remember const correctness
  // cast here as well:
  int (*arrptr)[dim3D->y][dim3D->z] = (int(*)[dim3D->y][dim3D->z]) dim3D->array;  

  // I cooked up a bit more "3D:ish" output:
  for (size_t i_x=0; i_x<dim3D->x; i_x++)
  {
    printf("[ ");
    for (size_t i_y=0; i_y<dim3D->y; i_y++)
    {
      printf("[ ");
      for (size_t i_z=0; i_z<dim3D->z; i_z++)
      {
        printf("%3.1d ", arrptr[i_x][i_y][i_z]);
      }
      printf("] ");
    }
    printf("]\n");
  }
}


int main() {
  size_t x,y,z;
  scanf("%zu %zu %zu", &x, &y, &z);  
  // sanity check x, y, z here....

  dim3D_t* dim3D;
  alloc_and_init_array(&dim3D, x, y, z);
  print_array(dim3D);

  free(dim3D); // remember to clean up
}

输入:

2 2 3

输出:

[ [   0   1   2 ] [  10  11  12 ] ]
[ [ 100 101 102 ] [ 110 111 112 ] ]

0
投票

使用函数来为您完成这项工作。

就像这样,您只能拥有一次分配,以及一种访问元素的简单方法。

这也允许您处理越界错误。

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

typedef struct
{
    int     x;
    int     y;
    int     z;
}       point;

typedef struct
{
    point   dim;
    point * array;
}       t_array;

point * at(const t_array s, int x, int y, int z)
{
    // can check error here
    return (s.array + x + s.dim.x * y + z * s.dim.y * s.dim.x);
}

int main(void)
{
    t_array s;
    size_t  i;

    i = 0;
    s.dim.x = 3;
    s.dim.y = 3;
    s.dim.z = 3;
    s.array = malloc(sizeof(point) * s.dim.x * s.dim.y * s.dim.z);
    if (s.array == NULL)
        return (1);

    for (int i_x = 0 ; i_x < 3; i_x++)
        for (int i_y = 0; i_y < 3; i_y++)
            for (int i_z = 0; i_z < 3; i_z++)
                at(s, i_x, i_y, i_z)->x = i++;

    for (int i_x = 0 ; i_x < 3; i_x++)
        for (int i_y = 0; i_y < 3; i_y++)
            for (int i_z = 0; i_z < 3; i_z++)
                printf("%d %d %d : %d\n", i_x, i_y, i_z, at(s, i_x, i_y, i_z)->x);
}
© www.soinside.com 2019 - 2024. All rights reserved.