如何在C中索引一个堆分配矩阵?

pjngdqdw  于 2022-12-02  发布在  其他
关注(0)|答案(2)|浏览(144)

我正在用C语言编写一个扫雷程序。
我有一个全局变量:

typedef struct box_t
{
  int box_type;
  int num_mines_bordering;
  int is_flagged;
} box_t;

// my global
box_t * gameboard = NULL;

稍后在应用程序中,它会根据行数和列数在堆中进行分配:

gameboard = (box_t *)malloc((rows * cols) * sizeof(box_t));

一切都很好,但是,我索引它的方式现在似乎是不正确的和容易出错的。我不能简单地做gameboard[x][y],因为我得到了编译器错误,我现在似乎是不正确的:

#define GET_LOC(ROW, COL) gameboard[(ROW * sizeof(box_t)) + (COL * sizeof(box_t)) * sizeof(box_t)]
// if you call this it would look like: box_t * loc = &GET_LOC(somerow, somecol);

有没有更好的索引方法?

3mpgtkmj

3mpgtkmj1#

编译器知道类型,因此知道每个数组条目的大小,因此唯一特殊的是列数cols

box_t *gameboard = malloc((rows * cols) * sizeof(*gameboard));
gameboard[row * cols + col] = ...;
tpxzln5u

tpxzln5u2#

您可以使用可变修改类型(VMT)(即指向VLA的指针)。问题是该 type 不能在文件范围内定义。最简单的解决方案是使用void*作为全局变量,使用VMT作为本地的、类型正确的视图。

void* gameboard_glob = NULL;
int gameboard_rows, gameboard_cols;

void allocate(int rows, int cols) {
  gameboard_rows = rows;
  gameboard_cols = cols;
  gameboard_glob = malloc(sizeof(box_t[rows][cols]);
}

void foo(void) {
  box_t (*gameboard)[gameboard_cols] = gameboard_glob;

  .. do stuff with `gameboard[r][c]`
}

或者,可以通过以下方式进行分配和方便的初始化:

box_t (*gameboard)[cols] = calloc(rows, sizeof *gameboard);

... initialize with gameboard[r][c]

gamebard_glob = gameboard;

使用简单的free(gamebard_glob)释放内存。
请注意,这种类型的VLA不会在堆栈上分配任何内存。所有内存都是从堆中分配的,使用malloc/calloc。此外,行数可以使用realloc更改。此解决方案需要任何符合C99的编译器,包括几乎所有主流编译器,除了声名狼借的MSVC。

相关问题