Home > Software engineering >  **array vs array[][]: are they both 2D arrays?
**array vs array[][]: are they both 2D arrays?

Time:12-08

My teacher told me that int **array is not a 2D array, it is just a pointer to a pointer to an integer. Now, in one of my projects I have to dynamically allocate a 2D array of structs, and this is how it is done:

struct cell **array2d = (struct x **)calloc(rows, sizeof(struct x *));
    
for (int i = 0; i < columns; i  ) {
    array2d[i] = (struct x *)calloc(j, sizeof(struct x));
}

But here we return a pointer to a pointer to the struct, so how is this a 2D array?

Before using dynamic allocation, I had a statically allocated array of the form: array2d[][]

Now that I replaced it by dynamic allocation, I also replaced array2d[][] by **array2d.
Every function that takes array2d[i][j] als argument now returns an error saying the types don't match.

Could someone explain me what is happening here? What is the difference between **array and array[m][n] and why is the compiler complaining?

CodePudding user response:

They're thoroughly different things.

An array is a sequence of values of the same type stored one after another in memory.

In C, an array is more or less interchangeable with a pointer to its first elementa[0] is *a,
a[1] is *(a 1), etc. — at least when we're talking about one-dimensional arrays.

But now consider:

int a[3][3];

in this case, a contains nine elements, contiguous in memory. a[0][0] through a[0][2], then a[1][0] immediately after, up until a[2][2]. *a is the same as a[0][0]. An expression like a[1] isn't meaningful.

If you pass a to a function, it would fit into a parameter type of int * or int[3][3] or int [][3] (knowing the "stride" of the second dimension is absolutely necessary to doing the math to look up a given element).

On the other hand:

int *b[3];
b[0] = malloc(...);
b[1] = malloc(...);
b[2] = malloc(...);

in this case, b is an array of 3 elements, each of which is a pointer to an array of 3 elements. You still access it like b[0]0] or b[1][2], but something completely different is happening under the hood. The elements aren't all stored contiguously in memory, and *b isn't any of them, it's a pointer. If we were to pass b to a function, we would receive it with a parameter of type int ** or int *[]. Knowing the length of each row in advance isn't necessary, and in fact each row could have a different length from the others. Some of the rows could even be null pointers, with no storage behind them for integers.

CodePudding user response:

Pointers and arrays are not the same thing and do not have the same functionality.

Think about implementing a graph. A graph has edges starting from nodes. It is clear that an edge corresponds to a pointer whose value is the address of other node. How would you think about an edge using an array ? -- it is possible (and some data structures such as heaps implement edges using arrays) but not so intuitive and incovenient many times.

Arrays are syntactic sugar in C -- they are all the time rewritten using pointer arithmetic, but pointers are not all the time thought as arrays.

Using double-pointers you can encode 2d arrays (seen as an array containing pointers to other arrays), while a [N][M] array is a single vector in memory that can be accessed in (x,y) as v[M*x y].

  • Related