在结构中需要“可变”大小的二维数组

Ric*_*ndo 3 c arrays struct multidimensional-array dynamic-memory-allocation

我正在尝试实现类似于Conway的生活游戏的单元格网格。

虽然每个单独的网格在两个维度上都应具有固定的大小,但我希望有一个Grid结构可以在两个维度上都具有任意大小。

这类似于如何将数组设置为任意大小,但是一旦初始化后的数组将具有固定的大小。

这是我到目前为止的内容:

typedef struct Cell {
    int data;
    // stuff to be added later
} Cell;

typedef struct Grid {
    unsigned width;
    unsigned height;
    Cell cell[][];
} Grid;

Grid initGrid(unsigned width, unsigned height) {
    Grid g;
    g.width = width;
    g.height = height;
    g.cell = malloc( sizeof(Cell)*width*height );
    return g;
}
Run Code Online (Sandbox Code Playgroud)

但是我收到以下编译时错误:

main.c|12|note: declaration of `‘cell’ as multidimensional array must have bounds for all dimensions except the first|
Run Code Online (Sandbox Code Playgroud)

如何定义Grid大小灵活的数据类型?

发布脚本:作为C新手,我认为以下方法会起作用:

typedef struct Grid {
    unsigned width;
    unsigned height;
    Cell cell[width][height];
} Grid;
Run Code Online (Sandbox Code Playgroud)

发表评论后:每当我使用时,我总是不安malloc。我在这里正在做(或试图做)可怕的错误吗?

unw*_*ind 5

您无法使用cell[x][y]C中的双索引()来做到这一点,无法表达每行要跳转的字节数是动态的。

因此,最好的方法(我认为)是使用一维数组手动进行索引。

放一个平原:

Cell *cell;
Run Code Online (Sandbox Code Playgroud)

struct(保持widthheight)中,然后像这样进行索引:

set_cell(Grid *g, unsigned int x, unsigned int y, Cell value)
{
  g->cell[y * g->width + x] = value;
}
Run Code Online (Sandbox Code Playgroud)

编译器将内联此代码的可能性不大,而且将会非常严格。可能比“锯齿状阵列”方法要快,后者使用更多的内存和另一层间接层。

分配很简单:

Grid initGrid(unsigned int width, unsigned int height)
{
    Grid g;
    g.width = width;
    g.height = height;
    g.cell = malloc(width * height * sizeof *g.cell);
    // add assert or error here, can't return NULL for value type
    return g;
}
Run Code Online (Sandbox Code Playgroud)

如果您也想进行堆分配Grid,则可以将其与其元素一起分配。

是的,您需要free()在完成分配后进行分配,以免泄漏内存。严格来说,在现代系统上,无论程序何时结束,OS都将释放所有资源,但是无论如何,这都是释放代码的好方法:

void destroyGrid(Grid g)
{
  free(g.cell);
}
Run Code Online (Sandbox Code Playgroud)