Search code examples
cmultidimensional-arraydynamicmallocdynamic-allocation

Can't declare a 2D dynamic array in a struct


So I have 2 questions.

I'm trying to learn how to dynamically allocate memory for 2D arrays. Here is a working code, I first want to know if it's fine, it works but I really don't know if I have memory leaks or some errors I don't see.

typedef struct Map Map;

struct Map
{
    int width, height;
    int** cases; // Not technically a 2D array but I use it like it in my code
};

int getMapValue(Map map, int x, int y);
void setMapValue(Map* map, int value, int x, int y);

void mallocMap(Map* map, int width, int height);
void freeMap(Map* map);

int main()
{
    int l,h,i,j;
    Map map;

    printf("Width : ");
    scanf("%d", &l);
    printf("Height : ");
    scanf("%d", &h);

    map.width = l;
    map.height = h;

    mallocMap(&map, l, h); // allocate memory for the map

    for(j = 0; j < map.height; j++)
        for(i = 0; i < map.width; i++)
            setMapValue(&map, i*j, i, j); // set some values

    for(j = 0; j < map.height; j++)
        for(i = 0; i < map.width; i++)
            printf("%d ", getMapValue(map, j, i)); // read some values, works fine

    freeMap(&map); // free memory

    return 0;
}

void mallocMap(Map* map, int width, int height)
{
    map->cases = malloc(sizeof(int) * width * height);

    if (map->cases == NULL)
    {
        printf("Error\n");
        exit(0);
    }
}

void freeMap(Map* map)
{
    free(map->cases);
}

int getMapValue(Map map, int x, int y)
{
    return *(map.cases + y*map.height + x);
}

void setMapValue(Map* map, int value, int x, int y)
{
    *(map->cases + y*map->height + x) = value;
}

Then I have a problem. I want to add a struct Player which has two Map elements in it like so :

struct Player
{
    Map map[2];
};

But this results in an error array has incomplete element type. Apparently it's because of the size of the array that isn't set correctly, how should I make this work ?

Update : I needed to write the Map structure before the Player structure.


Solution

  • The problem with the "incomplete type" is very likely because you define struct Player before having defined struct Map.

    Concerning your "2D"-Array: With map->cases = malloc(sizeof(int) * width * height);, you actually reserve memory in a layout similar to a "real" 2D-array, whereas datatype int **cases denotes a pointer to pointer to an int. So if you switch to int *cases, it should work.

    Note that cases still is not a "real" 2D-Array, since you are not allowed to access it like map->cases[3][4] (this would yield undefined behaviour). But you calculate the offsets on your own in the getter and setter functions anyway, so your implementation should work.