如何在C中的结构内初始化动态2D数组?

Adl

我想使用一个结构来包含一些数据并在程序中的不同函数之间传递它们,该结构必须包含一个动态2D数组(我需要一个矩阵),其尺寸根据程序参数而变化。所以这是我的结构:

    struct mystruct {
        int **my2darray;

    }

我有一个函数,可以从文件中读取数字,并且必须将每个数字分配给struct数组的单元格。

我尝试这样做:

    FILE *fp = fopen(filename, "r");
    int rows;
    int columns;
    struct mystruct *result = malloc(sizeof(struct mystruct));
    result->my2darray = malloc(sizeof(int)*rows); 
    int tmp[rows][columns];
    for(int i = 0;i<rows;i++) {
        for(int j = 0;j<columns;j++) {
            fscanf(fp, "%d", &tmp[i][j]); 
        }
        result->my2darray[i]=malloc(sizeof(int)*columns);
        memcpy(result->my2darray[i],tmp[i],sizeof(tmp[i]));
    }

但这给了我一个奇怪的结果:除第一行外,所有行均正确存储。(我确定问题不在扫描文件中)。如果我在此更改第四行代码:

    result->my2darray = malloc(sizeof(int)*(rows+1)); 

它工作正常。现在我的问题是为什么会这样?

伦丁

这是使用该语言的一些“新”功能的答案:灵活的数组成员和指向VLA的指针。

首先,请检查正确分配多维数组您将需要一个2D数组,而不是一些查找表。

要分配这样一个真正的2D数组,您可以利用灵活的数组成员:

typedef struct
{
  size_t x;
  size_t y;
  int flex[];
} array2d_t;

尽管将“分解”成一个维度,但它将被分配为一个真实的数组:

size_t x = 2;
size_t y = 3;
array2d_t* arr2d = malloc( sizeof *arr2d + sizeof(int[x][y]) );

因为灵活数组成员的问题在于它们既不能是VLA也不能是二维的。并且尽管将其强制转换为另一种整数数组类型是安全的(就别名和对齐而言),但语法相当邪恶:

int(*ptr)[y] = (int(*)[y]) arr2d->flex;  // bleh!

可能会将所有这些邪恶的语法隐藏在宏后面:

#define get_array(arr2d) \
  _Generic( (arr2d),     \
            array2d_t*: (int(*)[(arr2d)->y])(arr2d)->flex )

读为:如果arr2d类型为a,array2d_t*则访问该指针以获取flex成员,然后将其强制转换为适当类型的数组指针。

完整示例:

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

typedef struct
{
  size_t x;
  size_t y;
  int flex[];
} array2d_t;

#define get_array(arr2d) \
  _Generic( (arr2d),     \
            array2d_t*: (int(*)[(arr2d)->y])(arr2d)->flex )

int main (void)
{
  size_t x = 2;
  size_t y = 3;

  array2d_t* arr = malloc( sizeof *arr + sizeof(int[x][y]) );
  arr->x = x;
  arr->y = y;
  

  for(size_t i=0; i<arr->x; i++)
  {
    for(size_t j=0; j<arr->y; j++)
    {
      get_array(arr)[i][j] = i+j;
      printf("%d ", get_array(arr)[i][j]);
    }
    printf("\n");
  }

  free(arr);
  return 0; 
}

优于指针对指针的优势:

  • 可以通过单个函数调用分配/释放的实际2D数组,并且可以将其传递给诸如memcpy之类的函数。

    例如,如果您有两个array2d_t*指向分配的内存,则可以通过单个memcpy调用复制所有内容,而无需访问单个成员。

  • 结构中没有多余的混乱,只有数组。

  • 由于内存在整个堆中进行了分段,因此在访问阵列时不会丢失任何高速缓存。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章