If you have a type T and are going to allocate an array of size N then this expression
new T[N]
returns the address of the type T * of the first element of the allocated array.
So you should write
T *a = new T[N];
For example if T is equivalent to the type int
typedef int T;
or
using T = int;
then the above allocation can be written
int *a = new int[N];
the size of element of the array is equal to sizeof( int ) and usually is 4 bytes.
Now let's assume that you are going to allocate an array of elements of type int[M] where M is a constant integer expression.
You can write
typedef int T[M];
or
using T = int[M];
and
T *a = new T[N];
So you allocated an array of N elements where each element has size sizeof( int[M] and the pointer a points to the first element of the array.
Because T is equivalent tp int [M] you can write
int ( *a )[M] = new int [N][M];
that is this statement allocates an array of N elements of the type int[M] and the pointer a gets the address of the first element of the allocated array.
Returning to your program example
int r = 5
int (*a)[c];
a = new int[r][c];
you can rewrite it the following way
typedef int T[c];
or
using T = int[c];
and
T *a = new T[r];
that is this statements allocates an array of r elements (objects) of type int[c] and a is pointer to the first element of the allocated array.
ais declared to be a pointer to an array of 5int; that's it. it isn't pointing to anything (yet). That's what thenew []is for.int r=5int[][]) is an array of arrays which is very different from aint**int b[2][5]Thenint** pB = bis an error butint (*pb)[5] = bis not. That's why I said "a pointer (b) to an array of pointers (pb)".