This is a pointer to an array. It is not a pointer to a pointer. Arrays and pointers are different. An array has an address, but an array is not an address. An array is a series of contiguous elements.
This pointer points to the whole array and not just the first element, in the same way that a float * points to the whole float and not just the first byte.
If you have for example:
int foo[10];
int (*arrayABC)[10] = &foo;
then the expressions (*arrayABC) and foo are identical. E.g. foo[3] is the same as (*arrayABC)[3].
Videos
So if make an array like this:
int v[4][2];
I can’t assign v to:
int **pptr;
Instead I can assign it to:
int (*aptr)[2];
But I can pptr into a 2d array with malloc:
pptr = malloc( 4 * sizeof(int *));
for (int i = 0; i < 4; i++)
pptr[i] = malloc(2 * sizeof(int));Now I can assign a number to pptr[2][1] similar to v, but I can also assign pptr into another pointer pointer without any problems unlike v. This is so confusing, can someone explain why this happens?
This is a pointer to an array. It is not a pointer to a pointer. Arrays and pointers are different. An array has an address, but an array is not an address. An array is a series of contiguous elements.
This pointer points to the whole array and not just the first element, in the same way that a float * points to the whole float and not just the first byte.
If you have for example:
int foo[10];
int (*arrayABC)[10] = &foo;
then the expressions (*arrayABC) and foo are identical. E.g. foo[3] is the same as (*arrayABC)[3].
If you have an object of a type T then a pointer to the object is declared like
T obj;
T *ptr = &obj;
Now let's the type T is defined the following way
typedef int T[10];
Thus the code above
T obj;
T *ptr = &obj;
can be rewritten using the typedef definition like
int obj[10];
int (*ptr)[10] = &obj;
In the both cases, when T is some abstract type and when T is an alias for int[10], ptr is a pointer to an object. In the last case ptr is a pointer to an array of 10 elements of type int. That is the object pointed to by ptr has array type. Arrays and poiters are different types.
Try the following simple demonstrative program
#include <stdio.h>
int main( void )
{
typedef int T[10];
T a;
T *pa = &a;
printf( "%zu\n", sizeof( *pa ) );
int b[10];
int ( *pb )[10] = &b;
printf( "%zu\n", sizeof( *pb ) );
}
Its output is
40
40
As you can see the both values are equal to the size of an integer array of 10 elements. So the pointers point to arrays.
If you write
int *arrayABC[10];
you will get an array of 10 pointers of type int *.
If you write
int (*arrayABC)[10];
you will get a pointer to an array of 10 integers.
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
The third one is same as the first.
The general rule is operator precedence. It can get even much more complex as function pointers come into the picture.
Use the cdecl program, as suggested by K&R.
$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
It works the other way too.
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )