Es lo que se le conoce como apuntadores o punteros.
Un puntero es un tipo especial de variable, que almacena el valor de una direccion de memoria, esta direccion puede ser la de una variable individual, pero mas frecuentemente sera la de un elemento de un array, una estructura u objeto de una clase. Los punteros, al igual que una variable comun, pertenecen a un tipo (type), se dice que un puntero 'apunta a' ese tipo al que pertenece.
Para arrays bidimensionales, hay que hacerlo dimensión a dimensión; primero se define un puntero de punteros:
int **mapa;
Luego se reserva memoria para los punteros:
mapa=(int **)malloc(sizeof(int *)*N1);
y, por último, para cada puntero se reserva memoria para los elementos:
for(i1=0;i1<N1;i1++)
mapa[i1]=(int *)malloc(sizeof(int)*N2);
y ya puedes accesar a los elementos normalmente.
mapa[0][0]
mapa[5][4], etc.
en pocas palabras digamos que lo que tienes es una matriz de mxn
a11 a12 a13 a14 ... a1n
a21 a22 a23 a24 ... a2n
a31 a32 a33 a34 ... a3n
. . . . .
. . . . .
. . . . .
am1 am2 am3 am4 ... amn
Saludos!!!