le standard c++ dit que les éléments d'un tableau doivent être contigus
en mémoire. quand tu déclares:
int foo [x][y][z];
le type de foo est [un tableau de x [tableau de y [tableau de z [int]]]] 
pour y voir plus claire, c'est comme si tu avais fait "implicitement"
typedef int A[z]; // le type A est un tableau de z elements de type int contigus
typedef B A[y]; // le type B est un tableau de y elements de type A contigus
typedef C B[x]; // le type C est un tableau de x elements de type B contigus
C foo;
le type A est un tableau de int, pas de *int. en mémoire, A est {int1, int2, ..., intz}
et non {*int1, *int2, ..., *intz}. c'est la même chose pour les types B et C.
B est {A1, A2, ..., Ay}, pas {*A1, *A2, ..., *Ay} donc par extension B est
{{int1, int2, ..., intz}, {int1, int2, ..., intz}, ...} et ainsi de suite.
même si tu fait int foo[10][10][10][10][10], tout est contigu.
pour faire ce dont tu parles: déclarer un tableau de x pointeurs vers un tableau
de y int, il faut utilise la syntaxe suivante:
int (*a[x]) [y];
petite question
sachant qu'un pointeur équivaut a 4 bytes, quel est le
sizeof de a, de b, et de c ?
int (*a[10]) [10];
int (*b[10][10]) [10];
int (*(*c[10])[10]) [10];