Luego de explicar vectores en C, vamos a referirnos a otra implementación de los array: las matrices.
Una matriz podría definirse como un vector multidimensional, es decir un vector de dos o más dimensiones. En ellas se trabaja de la misma manera que con los vectores, sólo que en lugar de un solo índice tendremos tantos como dimensiones de nuestra matriz.
Declarando una matriz:
Para declarar una matriz, haremos exactamente lo mismo que en vectores (véase: Parte 1) sólo que agregaremos tantos índices como dimensiones queremos que tenga nuestra matriz.
Por ejemplo, si queremos declarar una matriz1 de enteros de 3 dimensiones 2x4x6 o una matriz2 de flotantes 3x3, lo haríamos como en la imagen.
Inicializando los elementos de una matriz:
Para inicializar los elementos de una matriz también lo haremos de la misma manera que en vectores.
*Podemos inicializarlas elemento a elemento usando los índices:
Aquí inicializamos el elemento [0][1] de nuestra matriz en 0 y el elemento [1][2] en 3.
Hay que recordar que los elementos que no inicialicemos en ningún valor contendrán basura.
*Podemos usar estructuras de control iterativas para inicializar los elementos de nuestra matriz:
Hay que tener en cuenta que necesitaremos tantas estructuras de control iterativas como dimensiones tenga nuestra matriz.
En el ejemplo anterior, inicializamos todos los valores de nuestra matriz en 0.
*O podemos inicializar los elementos de manera explícita:
Esta inicialización se puede hacer en una sola línea pero lo colocamos de esta manera para que vean que se inicializan por fila.
Usando scanf y printf con matrices:
Utilizaremos estas funciones de la misma manera que explicamos para vectores.
En el siguiente ejemplo en lugar de pedir uno por uno los elementos con scanf lo hacemos dentro de tantas estructuras iterativas como dimensiones tiene nuestra matriz:
Y hacemos lo mismo para mostrar los elementos con printf en este ejemplo:
Sólo que agregamos algunos espacios después de cada elemento y un salto de línea entre cada fila para que se vea en pantalla como una matriz. Si inicializáramos los 9 elementos de nuestra matriz 3x3 con los números del 1 al 9 con ese ejemplo obtendríamos algo así:
Disposición en memoria de los elementos de una matriz:
Para explicar este tema, tomaremos como ejemplo una matriz 3x3 (como la de nuestros ejemplos). Si pedimos prestada la definición al álgebra lineal la definición de matriz y la armamos tendríamos algo como esto:
Donde, si nos ponemos a recordar un poco o simplemente miramos el gráfico, los subíndices de cada elemento indican el primero la fila y el segundo la columna correspondiente.
En esta forma, si queremos por ejemplo el elemento a23 simplemente buscamos el elemento que se encuentra en la fila 2 y en la columna 3.
Hasta aquí podrán decir que no hay ninguna novedad y que incluso ya trabajamos en los ejemplos con este concepto de matriz y que hasta hicimos un printf que la mostraba en este formato ¿entonces para qué esta explicación?
La respuesta es que en C las direcciones de memoria no son multidimensionales ni mucho menos, sino que se encuentran una al lado de la otra. Entonces veamos lo que hace el compilador en estos casos.
Cuando se encuentra con la definición de una matriz, el compilador reserva tantas direcciones de memoria contiguas como se necesite para guardar todos los elementos de nuestra matriz. En el caso de la matriz de enteros 3x3 reservará el espacio necesario para guardar 9 enteros.
Dejando de lado la cantidad de memoria que ocupa cada tipo de dato (tema que explicaremos en una de las próximas entradas) y explicándolo de manera muy simple; el compilador reservará esas 9 posiciones contiguas, es decir una al lado de la otra con lo que nuestra matriz 3x3 en realidad sería algo como esto:
Para encontrar cada elemento a través de los 2 índices el compilador hará la operación ((i*3)+j) con lo que veamos qué obtendría en los 9 casos:
Si miramos bien obtuvimos las posiciones de nuestro esquema anterior.
En realidad a ese resultado el compilador lo multiplica por la cantidad de bytes que ocupa el tipo de dato correspondiente y ubica las posiciones a partir de la dirección de memoria de inicio de la matriz almacenada en su nombre, pero como ya dijimos esto lo veremos mejor en otra entrada.
Una matriz podría definirse como un vector multidimensional, es decir un vector de dos o más dimensiones. En ellas se trabaja de la misma manera que con los vectores, sólo que en lugar de un solo índice tendremos tantos como dimensiones de nuestra matriz.
Declarando una matriz:
Para declarar una matriz, haremos exactamente lo mismo que en vectores (véase: Parte 1) sólo que agregaremos tantos índices como dimensiones queremos que tenga nuestra matriz.
Por ejemplo, si queremos declarar una matriz1 de enteros de 3 dimensiones 2x4x6 o una matriz2 de flotantes 3x3, lo haríamos como en la imagen.
Inicializando los elementos de una matriz:
Para inicializar los elementos de una matriz también lo haremos de la misma manera que en vectores.
*Podemos inicializarlas elemento a elemento usando los índices:
Aquí inicializamos el elemento [0][1] de nuestra matriz en 0 y el elemento [1][2] en 3.
Hay que recordar que los elementos que no inicialicemos en ningún valor contendrán basura.
*Podemos usar estructuras de control iterativas para inicializar los elementos de nuestra matriz:
Hay que tener en cuenta que necesitaremos tantas estructuras de control iterativas como dimensiones tenga nuestra matriz.
En el ejemplo anterior, inicializamos todos los valores de nuestra matriz en 0.
*O podemos inicializar los elementos de manera explícita:
Esta inicialización se puede hacer en una sola línea pero lo colocamos de esta manera para que vean que se inicializan por fila.
Usando scanf y printf con matrices:
Utilizaremos estas funciones de la misma manera que explicamos para vectores.
En el siguiente ejemplo en lugar de pedir uno por uno los elementos con scanf lo hacemos dentro de tantas estructuras iterativas como dimensiones tiene nuestra matriz:
Y hacemos lo mismo para mostrar los elementos con printf en este ejemplo:
Sólo que agregamos algunos espacios después de cada elemento y un salto de línea entre cada fila para que se vea en pantalla como una matriz. Si inicializáramos los 9 elementos de nuestra matriz 3x3 con los números del 1 al 9 con ese ejemplo obtendríamos algo así:
Disposición en memoria de los elementos de una matriz:
Para explicar este tema, tomaremos como ejemplo una matriz 3x3 (como la de nuestros ejemplos). Si pedimos prestada la definición al álgebra lineal la definición de matriz y la armamos tendríamos algo como esto:
Donde, si nos ponemos a recordar un poco o simplemente miramos el gráfico, los subíndices de cada elemento indican el primero la fila y el segundo la columna correspondiente.
En esta forma, si queremos por ejemplo el elemento a23 simplemente buscamos el elemento que se encuentra en la fila 2 y en la columna 3.
Hasta aquí podrán decir que no hay ninguna novedad y que incluso ya trabajamos en los ejemplos con este concepto de matriz y que hasta hicimos un printf que la mostraba en este formato ¿entonces para qué esta explicación?
La respuesta es que en C las direcciones de memoria no son multidimensionales ni mucho menos, sino que se encuentran una al lado de la otra. Entonces veamos lo que hace el compilador en estos casos.
Cuando se encuentra con la definición de una matriz, el compilador reserva tantas direcciones de memoria contiguas como se necesite para guardar todos los elementos de nuestra matriz. En el caso de la matriz de enteros 3x3 reservará el espacio necesario para guardar 9 enteros.
Dejando de lado la cantidad de memoria que ocupa cada tipo de dato (tema que explicaremos en una de las próximas entradas) y explicándolo de manera muy simple; el compilador reservará esas 9 posiciones contiguas, es decir una al lado de la otra con lo que nuestra matriz 3x3 en realidad sería algo como esto:
Para encontrar cada elemento a través de los 2 índices el compilador hará la operación ((i*3)+j) con lo que veamos qué obtendría en los 9 casos:
En realidad a ese resultado el compilador lo multiplica por la cantidad de bytes que ocupa el tipo de dato correspondiente y ubica las posiciones a partir de la dirección de memoria de inicio de la matriz almacenada en su nombre, pero como ya dijimos esto lo veremos mejor en otra entrada.
Y llegamos al final de esta entrada, en la siguiente nos sumergiremos en las aguas de las cadenas de caracteres en C y veremos nuevas librerías para trabajar con ellas. Hasta la próxima.
Comentarios
Publicar un comentario