在C语言中使用malloc初始化结构体

3

很抱歉,我的问题可能比较初级。由于英语不是我的母语,所以请原谅我的语法错误。

我需要制作一个跳棋游戏。我已经定义了一些结构体,如下:

struct game {
int **board;
int xsize, ysize;

struct move *moves;
int cur_player;
};

struct coord {
int x, y;
};

struct move_seq {
struct move_seq *next;
struct coord c_old;
struct coord c_new; 
int piece_value;
struct coord piece_taken;
int old_orig;
};

struct move {
struct move *next;
struct move_seq *seq;
};

我需要使用函数初始化一个名为“game”的结构体。

struct game *new_game(int xsize, int ysize)

那么,这是我的问题。我现在总是以10和10的值调用new_game函数中的xsize和ysize参数。然后,我初始化游戏板,稍后想要分配它。

int black = 1;
int white = 5;
int **board;
int i;
int j;
int k;
for(i=0;i<xsize;i++)
{
    for(j=0;j<ysize;j++)
    {
        if(i<(xsize/2) && j<(ysize/2) && (i+j)%2!=0)
        {
            board[i][j] = black;
        }
        else if(i>(xsize/2) && j>(ysize/2) && (i+j)%2!=0)
        {
            board[i][j] = white;
        }
        else board[i][j] = 0;
    }
}
struct game *new = malloc (sizeof(struct game *));
if (new == NULL) return NULL;

所以,我的问题在于此。无论我对结构体new做什么,都会出现“分割错误”。
我尝试用new->xsize = xsize和ysize做相同的赋值。我为board和move进行了malloc,就像我学到的那样,但我仍然不断得到分割错误的错误。
所以这是我的真正问题:如何正确地分配和初始化结构体?我需要为struct game的每个成员分配一次malloc吗?(我也尝试过,但没有成功...)
我不仅仅想要答案,我更希望真正理解我在这种情况下和一般情况下应该做些什么,以便将来少犯错误。
感谢您的帮助。
祝你有一个美好的一天。

1
int **board; 这个指向指针的指针从未被初始化,它可以指向任何地方的指针。 - wildplasser
“new”是任何能够处理C++代码的编译器中的保留字,即使代码是C。因此,强烈建议将名称从“new”更改为更有意义且不是保留字的名称。 - user3629249
2个回答

6

发生这种情况是因为你只为你的struct分配了一个指针的空间。你需要做的是为整个结构体分配空间:

struct game *new = malloc (sizeof(struct game));

编辑:不要被malloc的返回值所误导,因为它返回的是分配空间的指针,这就是为什么应该使用struct game *new


0
除了Michael的错误修复,我还想问一下board的问题:它没有被分配,但你却对它进行了写入。我认为应该像这样:
struct game *new_game(int xsize, int ysize)
{
    int black = 1;
    int white = 5;
    int i;
    int j;

    struct game *new = malloc (sizeof(struct game));
    if (new == NULL) return NULL;
    game->xsize= xsize;
    game->ysize= ysize;
    game->board= malloc(xsize*ysize*sizeof(int));

    for(i=0;i<xsize;i++)
    {
        for(j=0;j<ysize;j++)
        {
            if(i<(xsize/2) && j<(ysize/2) && (i+j)%2!=0)
            {
                game->board[i*xsize+j] = black;
            }
            else if(i>(xsize/2) && j>(ysize/2) && (i+j)%2!=0)
            {
                game->board[i*xsize+j] = white;
            }
            else game->board[i*xsize+j] = 0;
        }
    }
    return (game);
}

请注意数组索引:编译器不知道动态行大小,所以您必须自己处理。

当我在其他地方使用时,我的板子会出现新的段错误。你给我的分配方式正确吗?当我搜索如何为2D数组分配内存时,我发现了另一种方法。就像我用循环为每一行分配内存的方式。再次感谢 :) - Lusheez
我的分配板和板索引是正确的。当你执行new->board = malloc(xsize*sizeof(int **));时,你为一个指针行(恰好是int大小)分配了空间,但你没有分配整个板。想一想:板有多少个方块?然后分配那么多内存。 - Paul Ogilvie
关于索引:您分配了一块线性内存,并必须将板放置在其中,作为行(x)的后面。然后要寻址第3行第2列,请向右移动2 * xsize,然后加1表示列(索引从零开始)。注意:如果编译器不知道行大小,则仅使用board [i] [j]进行索引无效。 - Paul Ogilvie
board是一个指向指针的指针,所以这行代码:'game->board= malloc(xsizeysizesizeof(int));' 是不正确的。一个可行的方法是board = malloc(ysize * sizeof(int*)),然后在循环中,为每一行分配内存,即board[row] = malloc(xsize * sizeof(int)),当然要检查每个malloc是否失败。 - user3629249
可以,也能工作。但可能会导致地址不太自然。 - Paul Ogilvie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接