This declaration
int (*p)[2]={{1,2}};
is syntactically incorrect. Pointers are scalar objects and they may be initialized by a single expression optionally enclosed in braces.
In this declaration
int (*p)[2]=(int **){{1,2},{3,4}}
you are trying to use a compound literal but again the initialization is incorrect because an object of the type int ** is a scalar object and my be initialized by a single expression.
In this declaration with a compound literal
int (*p)[2]=(int[][]){{5,4},{5,6}};
there is used an incorrect type specifier int[][] for a two-dimensional array because the size of elements of the array is unknown. You could write for example
int (*p)[2]=(int[][2]){{5,4},{5,6}};
That is you need to have an array that you will assign to a pointer. If you do not have such an array you can use a compound literal. For example
int (*p)[2] = (int[2][2]){{1,2},{3,4}};
or
int (*p)[2] = (int[][2]){{1,2},{3,4}};
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
enum { N = 2 };
int ( *p )[N] = ( int[N][N] ){ { 1, 2 }, { 3, 4 } };
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
int a[N][N] = { { 1, 2 }, { 3, 4 } };
p = a;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
int b[N] = { 1, 2 };
p = &b;
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", ( *p )[i] );
}
putchar( '\n' );
return 0;
}
The program output is
1 2
3 4
1 2
3 4
1 2