Drakalex
Drakalex

Reputation: 1538

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.

Upvotes: 0

Views: 58

Answers (2)

MFisherKDX
MFisherKDX

Reputation: 2866

I really don't know if I have memory leaks or some errors I don't see.

Yes. You have some memory problems during the allocation that has been pointed out by @StephanLechner.

Also, you have an arithmetic error that indexes the wrong elements and indexes outside the bounds of your array. Your x value ranges from 0 to width-1 and your y value ranges from 0 to height-1. Each time you increment y you are actually moving width elements in the array. So:

return *(map.cases + y*map.height + x);

Should be:

return *(map.cases + y*map.width + x);

Upvotes: 1

Stephan Lechner
Stephan Lechner

Reputation: 35154

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.

Upvotes: 2

Related Questions