int *p = malloc(sizeof(int) * 5);
Y ahora viene la parte curiosa y mi planteamiento:
int arr[5] es un array de enteros.
int (*p)[5] es un puntero a un array de 5 enteros.
Lo único que tienen en común los dos son el tipo de dato, int, y el tamaño del array, 5. El nombre que le demos no tiene imporancia. Si se obvia dicho nombre nos debería dar un tamaño pero sin declarar nada.
Por tanto el código antes escrito podría codificarse de una forma un poco más intuitiva:
int *p = malloc( sizeof(int[5]) );
Y funciona, al menos con GCC.
>>> Editado porqué estas líneas no tienen un sentido práctico <<<
int *p = malloc( sizeof(int[5][5]) );
y
int **p = malloc( sizeof(int[5][5]) );
>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<
¿Qué os parece?