I tried to assign two fixed-size arrays to an array of pointers to them, but the compiler warns me and I don't understand why.
int A[5][5]; int B[5][5]; int*** C = {&A, &B};
This code compiles with the following warning:
warning: initialization from incompatible pointer type [enabled by default]
If I run the code, it will raise a segmentation fault. However, if I dynamically allocate A
and B
, it works just fine. Why is this?
Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type.
The pointer ptr, and all pointers, are 8 bytes, because they hold addresses, which are 8 bytes, or 64 bits. Assigning any address to an array variable is not allowed.
The length of an array is established when the array is created. After creation, its length is fixed.
Pointer to an array points to an array, so on dereferencing it, we should get the array, and the name of array denotes the base address. So whenever a pointer to an array is dereferenced, we get the base address of the array to which it points.
If you want a declaration of C
that fits the existing declarations of A
and B
you need to do it like this:
int A[5][5]; int B[5][5]; int (*C[])[5][5] = {&A, &B};
The type of C
is read as "C
is an array of pointers to int [5][5]
arrays". Since you can't assign an entire array, you need to assign a pointer to the array.
With this declaration, (*C[0])[1][2]
is accessing the same memory location as A[1][2]
.
If you want cleaner syntax like C[0][1][2]
, then you would need to do what others have stated and allocate the memory dynamically:
int **A; int **B; // allocate memory for A and each A[i] // allocate memory for B and each B[i] int **C[] = {A, B};
You could also do this using the syntax suggested by Vlad from Moscow:
int A[5][5]; int B[5][5]; int (*C[])[5] = {A, B};
This declaration of C
is read as "C
is an array of pointers to int [5]
arrays". In this case, each array element of C
is of type int (*)[5]
, and array of type int [5][5]
can decay to this type.
Now, you can use C[0][1][2]
to access the same memory location as A[1][2]
.
This logic can be expanded to higher dimensions as well:
int A[5][5][3]; int B[5][5][3]; int (*C[])[5][3] = {A, B};
Unfortunately there's a lot of crappy books/tutorials/teachers out there who will teach you wrong things....
Forget about pointer-to-pointers, they have nothing to do with arrays. Period.
Also as a rule of thumb: whenever you find yourself using more than 2 levels of indirection, it most likely means that your program design is fundamentally flawed and needs to be remade from scratch.
To do this correctly, you would have to do like this:
A pointer to an array int [5][5]
is called array pointer and is declared as int(*)[5][5]
. Example:
int A[5][5]; int (*ptr)[5][5] = &A;
If you want an array of array pointers, it would be type int(*[])[5][5]
. Example:
int A[5][5]; int B[5][5]; int (*arr[2])[5][5] = {&A, &B};
As you can tell this code looks needlessly complicated - and it is. It will be a pain to access the individual items, since you will have to type (*arr[x])[y][z]
. Meaning: "in the array of array pointers take array pointer number x, take the contents that it points at - which is a 2D array - then take item of index [y][z] in that array".
Inventing such constructs is just madness and nothing I would recommend. I suppose the code can be simplified by working with a plain array pointer:
int A[5][5]; int B[5][5]; int (*arr[2])[5][5] = {&A, &B}; int (*ptr)[5][5] = arr[0]; ... ptr[x][y][z] = 0;
However, this is still somewhat complicated code. Consider a different design entirely! Examples:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With