-1

I know that there have been posted some questions about 2d arrays with malloc, however, I would like to refer to the answer to one of those questions.

I cannot visualise the realisation of the following fragment:

Allocate an array of M rows of N columns like this:

int (*array)[N] = malloc(M * sizeof *array);
  1. If we have M rows, why does *array have N parameter?
  2. What is the size of the *array (also as a number)? I understand the result of the part with malloc() only as M*N, but single block (1d) of the structure.
  3. How does M size, passed only in malloc, becomes number of rows? How does it become *array[M][N]?

I would appreciate your answers.

Question
  • 43
  • 7
  • 1
    1. `N` is the number of columns. 2. `*array` is an array of `N` `int`s, so `sizeof *array` equals `N * sizeof(int)`, and `M * sizeof *array` equals `M * N * sizeof(int)`. 3. `malloc(M * sizeof *array)` is equivalent to `malloc(M * N * sizeof(int))`. Unlike declared objects, blocks allocated by `malloc` do not have an effective type, only an allocated size. – Ian Abbott Dec 18 '20 at 13:29
  • 1
    The allocated block has the correct size and alignment so that it can hold the contents of an `int[M][N]`. The return value of `malloc` is converted to the type of `array`, which is `int(*)[N]` (a pointer to an array of `N` `int`s). In the expression `array[i][j]`, the `array[i]` selects a row of type `int[N]` which is an array of `N` `int`s. The array is converted by the expression to an `int *` pointing to the first element of the row. The `[j]` operates on that `int *` to select a particular element of the row. So effectively `array[i][j]` selects an element at a row and column. – Ian Abbott Dec 18 '20 at 13:47
  • Thank you for your answers, it starts to be clearer for me. However, could you tell me, why does these questions are so bad that the post is downvoted? – Question Dec 18 '20 at 13:56

1 Answers1

1

If we have M rows, why does *array have N parameter?
How does M size, passed only in malloc, becomes number of rows?

The code in the question is a simplified version of the most correct way to write the expression:

int (*array)[M][N] = malloc(sizeof *array);

This form is however problematic to use, because now we must access the array as (*array)[i][j] which is strange and cumbersome.

Therefore there's a trick to leave out the left-most dimension and use a pointer to the first element instead. The first element of an int [M][N] is a int [N] and a pointer to such an element is int(*)[N].

With int (*array)[N] we can access the array as array[i][j], where the [i] is pointer arithmetic on a int(*)[N] type and the [j] is pointer arithmetic on a int* (a decayed int [N] array).

What is the size of the *array

It is sizeof(int [N]) bytes, or if you will sizeof(int)*N bytes.

More details can be found here: Correctly allocating multi-dimensional arrays

Lundin
  • 195,001
  • 40
  • 254
  • 396