Comentario
§1 Hemos afirmado que en las matrices se cumplen las relaciones:
Matriz de una dimensión: &m[0] == &m == m
Matriz de 2 dimensiones: &m[0][0] == &m == *m
Matriz de 3 dimensiones: &m[0][0][0] == &m == **m
Matriz de 4 dimensiones: &m[0][0][0][0] == &m == ***m
etc.
§2 y que estas relaciones se traducen en que el tipo del identificador m de una matriz de objetos tipoX es:
Matrices unidimensionales: tipoX* (puntero-a-tipoX).
Matrices bidimensionales: tipoX** (puntero-a-puntero-a-tipoX).
Matrices tridimensionales: tipoX*** (puntero-a-puntero-a-puntero-a-tipoX).
etc.
La afirmación anterior puede resultar escandalosa, o al menos sorprendente, dado que una interrogación al compilador en este sentido parece contradecirla. En efecto:
int m[2][3] = {{10,9,8},{7,6,5}};
cout << typeid(m).name() << endl; // -> int[2][3]
§3 La salida obtenida indica que el tipo de m es realmente matriz de enteros de dos dimensiones con 2 y
3 elementos respectivamente. Sin embargo podemos comprobar la veracidad de los enunciados anteriores §2
y suponer que m es un puntero-a-puntero-a-int:
cout << **m << endl; // -> 10
cout << *(*m+1) << endl; // -> 9
cout << *(*m+2) << endl; // -> 8
cout << *(*m+3) << endl; // -> 7
cout << *(*m+4) << endl; // -> 6
cout << *(*m+5) << endl; // -> 5
§4 Las salidas proporcionadas son las adecuadas, y exactamente análogas a las que podrían obtenerse utilizando una notación de subíndices:
cout << m[0][0] << endl; // -> 10
cout << m[0][1] << endl; // -> 9
cout << m[0][2] << endl; // -> 8
cout << m[1][0] << endl; // -> 7
cout << m[1][1] << endl; // -> 6
cout << m[1][2] << endl; // -> 5
En realidad, el compilador utiliza internamente las expresiones con aritmética de punteros (§3
). La razón es la ya señalada, de que para el compilador
una expresión del tipo m[a][b] es equivalente a una expresión de puntero:
*( *( m + a ) + b ).