Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.3.8  Matrices como argumento de funciones

§1  Observación

No confundir el paso de una matriz en su conjunto (multidimensional o no) como argumento de una función, con el paso de un elemento de una matriz. Ejemplo:

int dias[2][12] = {
   {31,28,31,30,31,30,31,31,30,31,30,31},
   {31,29,31,30,31,30,31,31,30,31,30,31} };
....
x = fun1(dias, f, c, d, e);   // paso de matriz
z = fun2(dias[f][c], d, e);   // paso de elemento

§2  Sinopsis

Cuando hay que pasar una matriz bidimensional como argumento a una función, la declaración de parámetros formales de esta debe incluir el número de columnas, ya que la función receptora debe conoce la estructura interna de la matriz, para poder para acceder a sus elementos, y esto solo es posible informándole de su tipo y dimensiones. En el caso que nos ocupa las dimensiones son dos, por lo que la definición de la función llamada sería algo así:

func (int dias[2][12]) {...}      //  §2a

Observe que en la expresión anterior está incluida toda la información necesaria: número de filas, número de columnas y tamaño de cada elemento (un int). Desde luego la función receptora necesita conocer también la dirección de inicio del almacenamiento, pero ya hemos señalado ( 4.3.2) que "el identificador de una matriz puede ser utilizado como un puntero a su primer elemento", con lo que si mentalmente sustituimos dias por un puntero al número 31 (primer elemento) de la primera matriz, la información pasada es completa.


§3  Ya se ha señalado que C++ no contiene operadores para manejar matrices como una sola unidad ( 4.3.1). Al contrario de lo que ocurre en otros lenguajes (por ejemplo Java), en C++ es responsabilidad del programador no salirse del ámbito de la matriz al acceder a sus elementos, lo que una vez aceptado, nos conduce a que en realidad es innecesario conocer la primera dimensión. En efecto, en nuestro caso, el primer elemento (primera sub-matriz), es accedido directamente mediante el puntero dias; su tamaño ya lo conocemos (12 int), y con esta información es suficiente para acceder a cualquier otro elemento n. Solo es necesario desplazar el puntero los las posiciones de memoria correspondientes.

La conclusión anterior estaba ya implícitamente establecida en ( 4.3.6), donde hemos visto que, en una matriz bidimensional m[F][C], la posición Pf,c respecto del comienzo del elemento m[f][c] viene determinado por:

Pf,c  = ( C * f ) + c

expresión que es independiente del valor F (número de filas). Como consecuencia, la definición §2a podría ser del tipo:

func (int dias[][12]) {...}      // §3a


El primer paréntesis vacío es necesario para colocar el segundo, que es el que interesa. La expresión es conceptualmente equivalente ( 4.3.2) a:

func (int (*dias)[12]) {...}     // §3b

que indica explícitamente el hecho de que el parámetro es un puntero-a-matriz de 12 int.


§4  Comprobamos la veracidad de lo expuesto a un sencillo ejemplo:

#include <stdio.h>
void  escribe(int a[][12], int x, int y);   // prototipo
void  escribo(int (*a)[12], int x, int y);  // prototipo
 
void main () {         // =============
  int dias[2][12] = {
     { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12},
     {13,14,15,16,17,18,19,20,21,22,23,24}
  };
  escribe(dias, 1, 3);
  escribe(dias, 0, 7);
  escribo(dias, 1, 3);
  escribo(dias, 0, 7);
}
 
void escribe(int a[][12], int f, int c) {    // definición
   printf("Valor [%2i,%2i] = %3i\n", f, c, a[f][c]);
}
 
void escribo(int (*a)[12], int f, int c) {   // definición
   printf("Valor [%2i,%2i] = %3i\n", f, c, a[f][c]);
}

Salida:

Valor [ 1, 3] = 16
Valor [ 0, 7] =  8
Valor [ 1, 3] = 16
Valor [ 0, 7] =  8