2
int (*mapTerrain)[10] = (int (*)[10])malloc(sizeof(int[10][10]));
free(mapTerrain);

Someone on this site suggested these 2 lines for working with dynamical 2d arrays in C. Dimensions are [10][10]. Problem is, I'm not sure I understand them correctly. If I had to explain these 2 lines I'd say the following:

On the left we have an array of int pointers with size 10. (Can't explain the casting, I myself would expect it to be int *).

What's being passed to malloc is an array of int-s sized [10][10]. (Why isn't it ...malloc(sizeof(int*10*10));?) What allows us to pass an array to malloc instead of size_t size?

As for the free(mapTerrain); line. How come one free is enough? From what I remember you have to call free for every row of a dynamical 2d array.

Lundin
  • 195,001
  • 40
  • 254
  • 396
Platon Makovsky
  • 275
  • 3
  • 13
  • 1
    `int (*p)[10]` is not an array of `int*`, it's a pointer to a `int[10]`. (The first would be `int* p[10]`). – alain May 31 '18 at 08:43

1 Answers1

3

The cast of the result of malloc is just clutter and not necessary.

The most correct, formal version would be:

int (*mapTerrain)[10][10] = malloc(sizeof(int[10][10]));

This is an array pointer to a int [10][10] array. However, such a pointer is a bit painful to work with in practice, since to get an item we have to do:

  • *mapTerrain to get the array pointed at from the array pointer.
  • (*mapTerrain) parenthesis to not trip over operator precedence.
  • (*mapTerrain)[i][j] to get a single item.

As a trick, we can instead use a pointer to the first element of the int[10][10]. The first element is of type int[10], and so an array pointer to that element is int(*)[10]. With this type, we can do mapTerrain[i][j] as expected, because i means "give me array number i" through pointer arithmetic.

This trick is essentially the same thing as when we do something like

char* ptp = malloc(sizeof("hello"));` 

Here we don't point to the whole array either, we point at the first element of it.


sizeof(int[10][10]) is 100% equivalent to sizeof(int*10*10) (or 400 for that matter), but the first is self-documenting code, showing that we are expecting to use the allocated data as an array int[10][10].


One free is enough because there is just one malloc. You allocate the whole 2D array as a contiguous chunk of memory.

Further reading: Correctly allocating multi-dimensional arrays.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for clearing up almost everything. Only thing still unclear is the casting however. I'm working in Visual Studio, where it's required. – Platon Makovsky May 31 '18 at 08:45
  • 2
    @Oleg - The casting is required if you compile your C code as C++. Generally not a good idea.. – Bo Persson May 31 '18 at 08:52