Hola.
La disposición en memoria de un arreglo bidimensional es como la segunda imagen que pusiste.
Tu confusión seguramente venga de estas frases:
"Una matriz es un arreglo de arreglos de tipo T (supongamos de tipo char)"
Esto es cierto
"Y un arreglo es un puntero a la direccion del primer elemento"
Esto es incorrecto
Un arreglo es una colección de N elementos dispuestos en memoria secuencialmente (uno despues del otro). Cada elemento del arreglo tiene cierto tamaño fijo y uno puede calcular la dirección de comienzo del i-ésimo elemento sumando a la dirección del primer elemento la multiplicación de i por el tamaño de cada elemento del arreglo.
La "definición" de arreglo se puede aplicar "recursivamente" para arreglos multidimensionales.
Entonces por ejemplo supongamos que tenés una matriz bidimensional de caracteres de 5x4
char M[5][4] ;
lo que estás definiendo es un arreglo de 5 arreglos de 4 caracteres cada uno.
Cada arreglo de 4 caracteres ocupa 4 bytes, entonces sea D la dirección de comienzo del primer arreglo de 4 caracteres, M[0].
Como cada subarreglo contiene 4 caracteres el segundo subarreglo (M[1]) comienza en la dirección D+4*1 = D+4.
El tercer subarreglo (M[2]) comienza en la dirección D + 4*2 = D+8
El cuarto subarreglo (M[3]) comienza en la dirección D + 4*3 = D+12
Y el último subarreglo (M[4]) comienza en la dirección D + 4*4 = D+14
Una vez que accedés a un subarreglo, podes ubicar el elemento j-ésimo de manera similar, sumando a la dirección de comienzo del subarreglo la multiplicación de j por el índice que queres acceder.
Entonces para acceder al caracter M[i][j] se calcula D + 4*i + j
La confusión posiblemente venga de que hayas utilizado una construcción del C particular que es la inicialización de una estructura "puntero a caracter".
Esta definición:
char *string = "hola";
tiene un efecto similar (pero no idéntico) a esta definición:
char string[4] = "hola";
Y en particular la diferencia puede verse cuando uno define un arreglo multidimensional.
No es lo mismo
char matrizA[4][4];
que
char* matrizB[4];
que
char ** matrizC;
MatrizA ocupa 16 bytes, 4 bytes por cada uno de los 4 arreglos. Y refleja el segundo dibujo que pusiste.
Supongamos una arquitectura de 32 bits donde los punteros ocupan 4 bytes
MatrizB ocupa también 16 bytes, 4 bytes por cada puntero de los 4 que se definieron. Cada puntero apunta a la dirección de comienzo de una cadena de caracteres. Si además inicializas cada subarreglo con 4 caracteres entonces el total de memoria que consume sería 16 + 4*4 = 32 bytes. Es el primer dibujo que pusiste
y Matriz C ocupa 4 bytes, que corresponden al puntero donde uno puede almacenar un arreglo de punteros a char. Si además inicializas los punteros con datos para tener una matriz de 4*4 entonces la estrucutra en memoria termina ocupando 4 + 32. El esquema sería similar al de tu primer dibujo pero agregando el puntero al arreglo de punteros a char.
La disposición en memoria de cada una de esas estructuras es distinta. Cuando uno programa en C utilizando los inicializadores de punteros el compilador se encarga de asignar la memoria para cada arreglo y coloca el puntero a la dirección de comienzo del mismo.
Saludos,
Gustavo