Home > Mobile >  how can i have a struct have an unknown size array member?
how can i have a struct have an unknown size array member?

Time:02-10

im trying to make a sort of minesweeper clone in c, but i cant figure out how to create a variable length array member of a struct and initialize it.

my struct definitions

typedef struct Cell
{
    Rectangle area;         // The area the cell covers
    bool hasMine;           // If the cell covers a mine
    bool covered;           // If the cell is currently covered
    int touching;           // How many mines the cell is touching
} Cell;

typedef struct Minefield
{
    int columns;        // The amount of columns
    int rows;           // The amount of rows
    int mines;          // The amount of mines
    Cell field[];       // An array of columns*rows Cells

} Minefield;

how im creating new instances of a Minefield

Minefield NewGame(int columns, int rows, int mines)
{
    int i = 0;

    Cell cells[columns*rows];

    for (i=0; i < columns*rows; i  ) {
        int x = 0;
        int y = 0;

        if (i == 0) {
            Rectangle area = (Rectangle){0, 0, cellsize, cellsize};
            cells[i] = (Cell){area, false, true, 0};
        }
        else {
            Cell previous = cells[i-1];

            x = previous.area.x   cellsize;
            y = previous.area.y   cellsize;

            Rectangle area = (Rectangle){x, y, cellsize, cellsize};
            cells[i] = (Cell){area, false, true, 0};
        }
        
    }

    Minefield field = (Minefield){columns, rows, mines, cells};
    return field;
}

im new to c, ive done some googling and ive come across some very similar questions, but i cant really understand them or the examples they give. i think you can do what my errendous code is trying to do (or something very similar) with a gcc extension, but i want my code to be portable. how can i have a struct have an unknown size array member?

CodePudding user response:

Yes, it's called flexible array member. It's usually used with dynamically allocated objects. However, you cannot return Minefield by value. The compiler will copy only sizeof(Minefield) data what is the size of object if length of array Minefield::field was 0.

You can do:

Minefield* NewGame(int columns, int rows, int mines)
{
    Cell cells[columns*rows];
    ...
    // allocate memory for Minefield and cells array just after it
    Minefield* minefield = malloc(sizeof(*minefield)   sizeof cells);
    if (!minefield) { ... error handling ... }

    // set normal fields using compund literal
    *minefield = (Minefield){columns, rows, mines};

    // copy cells `array` to `minefield->field` array
    memcpy(minefield->field, cells, sizeof cells);

    return minefield;
}

The memcpy can be avoided by first allocating Minefield and writing directly to field member.

Minefield* NewGame(int columns, int rows, int mines)
{
    Minefield* minefield = malloc(sizeof(Minefield)   rows * columns * sizeof(Cell));
    if (!minefield) { ... error handling ... }
    *minefield = (Minefield){columns, rows, mines};

    Cell *cells = minefield->field;
    ...
    return minefield;
}

CodePudding user response:

Unfortunately, C doesn't have any built-in dynamic array like python. However, if you want to use some dynamic array either you can implement your self or you can see the answer to that link C dynamically growing array which explains that you need to have starting array with a default size, and then you can increase the size of the array which depends on your algorithm. After you import that header file provided by @casablance, you can simply use it for your minesweeper game.

  • Related