snakeGame * createSnakeGame()
{
int row = 10;
int col = 10;
snakeGame * game = (snakeGame *) malloc(sizeof(snakeGame));
game->rows = row;
game->columns = col;
for (int i = 0; i < row; i++)
{
if (i == 0 || i == row - 1)
{
for (int j = 0; j < col; j++)
{
game->board[i][j] = BORDER;
}
}
else
{
game->board[i][0] = BORDER;
game->board[i][col - 1] = BORDER;
}
}
return game;
}
typedef struct
{
snakeEntity ** board;
int rows;
int columns;
} snakeGame;
typedef enum
{
SNAKE_HORIZONTAL,
SNAKE_VERTICAL,
SNAKE_UP_RIGHT,
SNAKE_UP_LEFT,
SNAKE_DOWN_RIGHT,
SNAKE_DOWN_LEFT,
FOOD,
BORDER,
EMPTY
} snakeEntity;
int main()
{
snakeGame * game = createSnakeGame();
printf("Success");
return 0;
}
没有到达打印语句,因为程序在随机时间后挂起并突然退出。
我尝试过以不同的方式分配结构,例如计算数组大小和单独初始化板。但是,相同的 UB 仍然存在。
// Adding the array size to the allocated memory
snakeGame * game = (snakeGame *) malloc(sizeof(snakeGame) + (row * col * sizeof(snakeEntity)));
// Allocating memory to each row individually to the size of the column
game->board = (snakeEntity **) malloc(row * sizeof(snakeEntity));
for (int i = 0; i < row; i++)
{
game->board[i] = (snakeEntity *) malloc(col * sizeof(snakeEntity));
}
// Initialising the board separately
snakeGame * game = (snakeGame *) malloc(sizeof(snakeGame));
snakeEntity ** board = (snakeEntity **) malloc(row * col * sizeof(snakeEntity));
game->board = board;
我将不胜感激有关如何解决问题的建议。
在循环中分配给
board
成员之前,您不为其分配空间:game->board[i][j]
.
至于
snakeEntity ** board = (snakeEntity **) malloc(row * col * sizeof(snakeEntity));
,这也是错误的。 board**
不是二维数组,不能作为一个数组使用。但是,它可以用作指向指针数组中第一项的指针,以模拟二维数组。在那种情况下,正确的用法是:
game->board = malloc(row * sizeof(snakeEntity));
for(size_t i=0; i<row; i++)
{
game->board[i] = malloc(col * sizeof(snakeEntity));
}
然后
free()
以同样的方式。
但是,指向指针版本的指针是幼稚的(很多烂书和烂老师都在宣扬它)。查看正确分配多维数组
有几种方法可以使用二维数组而不是指针到指针来实现。一个例子是使用一个灵活的数组成员。不幸的是,灵活的数组成员只支持声明的一维数组,但我们可以使用一个作为二维数组指针的占位符。然后永远不会真正访问它作为它被声明为的一维数组。
它以可读性为代价提供了非常高效的代码。例子:
typedef struct
{
size_t rows;
size_t cols;
snakeEntity board[];
} snakeGame;
然后您将一次性分配所有内容:
snakeGame* game = malloc (sizeof(snakeGame) + sizeof(snakeEntity[ROWS][COLS]));
game->rows = ROWS;
game->cols = COLS;
...
free(game); // and later free on a single line
board
未初始化但现在指向分配的二维数组(充满垃圾)。
我们可以通过转换为适当的指针类型来填充它(这是难以阅读的部分):
snakeEntity (*board)[game->cols] = (snakeEntity(*)[game->cols]) game->board;
我们现在可以使用这个指针来填充或以其他方式访问二维数组,使用二维数组语法:
for(size_t i=0; i<game->rows; i++)
{
for(size_t j=0; j<game->cols; j++)
{
board[i][j] = whatever;
}
}