Programación En C: Matrices Con Punteros

Este artículo es parte de una serie – Cómo programar cualquier cosa: C Programación

Prefacio

En artículos anteriores, hemos discutido sobre punteros y matrices. En cada artículo los discutimos generalmente por separado, pero en el lenguaje de programación C, los arreglos y punteros en realidad están comúnmente vinculados entre sí. Esto se debe a que cada pieza de funcionalidad ofrece una forma diferente de ver casi lo mismo. A este respecto, puede ver tipos de punteros y matrices como perspectivas del mismo tema: elementos contiguos en la memoria. Como recordará con suerte, cuando se declara una matriz en C, se asigna una porción continua de memoria y se reserva para ella. Si hay 12 elementos en la matriz, entonces 12 fragmentos de memoria uno al lado del otro, cada uno después del último, se configuran y reservan en el programa. Como esperamos recordar, cuando incrementa un puntero accede al siguiente punto en la memoria igual al tamaño del tipo de base de la matriz. A partir de estos dos hechos, puede ver cómo se relacionan los punteros y las matrices.

Matrices Y Punteros

Digamos que especificamos una matriz int de 10 elementos así:

Podemos generar un puntero al primer elemento de la matriz simplemente especificando el nombre de la matriz sin un índice.

Esto es equivalente a escribir:

Y, de hecho, ambos son una programación válida de C, sin embargo, casi nunca verás la segunda forma en la práctica. Esto se debe a que es torpe escribir e implica más caracteres, lo que aumenta las posibilidades de error.

Esto es posible porque puede pensar en una matriz por sí misma, sin indexación, simplemente como un puntero al primer elemento de la matriz. De hecho, el acto de indexación podría considerarse una forma abreviada de la aritmética del puntero real realizada “detrás de escena”. Por ejemplo, cuando accede a myArray [3] está en esencia accediendo al tercer valor int en una serie de valores int. De esta forma, si tuviera un puntero al primer elemento de la matriz y luego le añadiera 3 (aritmética del puntero) accedería a la misma dirección de memoria que cuando indexó myArray [3]. Recuerde que incrementar un puntero lo hace apuntar a la siguiente dirección de memoria relativa a su tipo de base. Para aclarar esto, mira el siguiente diagrama:

En este ejemplo myArray [2] es equivalente a * (myPtr + 2). Recuerde que un puntero se incrementa en relación con su tipo de datos base, en este caso un int. Entonces al sumar 2 a myPtr hace que apunte dos entradas adelante en la memoria, del mismo modo cuando accede myArray [2] está accediendo al tercer int almacenado en la memoria contigua de la matriz. Estas son dos formas de acceder al mismo valor en la memoria. De hecho, se pone más raro …

Una vez que tenga un puntero de tipo base igual que su matriz y lo asigne a la dirección del primer elemento de la matriz como lo hicimos en el bloque de código anterior, puede usar el mecanismo de índice en el puntero como si fuera una matriz en sí. Creo que un fragmento de código puede ilustrarlo más a fondo:

Entonces, como en el diagrama anterior, puedes pensar en el mecanismo de índice (myArray [#]) como short hand para * (myArrayPointer + #)

Las matrices multidimensionales son iguales. Cuando C crea una matriz multidimensional, esencialmente establece cada fila una tras otra en la memoria, por lo que el último elemento de la fila 1 está justo al lado del primer elemento de la fila 2, y así sucesivamente. Aún puede usar la aritmética del puntero para acceder a estas matrices. La taquigrafía simplemente crece un poco para acomodar la dimensión extra:

Por supuesto, a medida que agrega más dimensiones, más confuso y enrevesado se vuelve, así que nos detendremos en dos dimensiones.

El objetivo de esto es que las matrices son simplemente secuencias de valores alineadas una después de la otra en la memoria. Debido a que los punteros y su aritmética operan de la misma manera, agregar uno a un puntero lo salta a la siguiente dirección de su tipo base en la memoria, ofrecen una forma alternativa de acceder a las matrices.

Matriz Como Tipo De Puntero Base

Es posible hacer que el tipo de base de un puntero sea realmente una matriz. En este sentido, si el tipo de base del puntero es de longitud 10, cada vez que incrementemos el puntero saltará 10 elementos adelante en la memoria. Esto se hace con un cambio sutil en nuestra declaración de puntero:

Este es un puntero de matriz multidimensional, lo que significa que en su base apunta a cada fila de una matriz. Es indexable del mismo modo que indexaría una matriz bidimensional. Pero si realiza la aritmética del puntero en él, en lugar de saltar el tamaño de un carácter en la memoria, saltará el tamaño de 10 caracteres en la memoria. Puede agregar más dimensiones después del 10 para crear matrices adicionales dentro de las matrices. Este tipo de puntero es un ejemplo de cómo se puede configurar un puntero para tratar con una matriz multidimensional.

La clave aquí es que indexar el puntero como se muestra arriba todavía funciona correctamente ya que este fragmento de código demuestra:

Puede ver cómo puede definir un puntero que vaya a acceder a una matriz multidimensional de la misma manera que la matriz original. Puede elegir acceder a una matriz multidimensional con un puntero recto de una sola dimensión como se indica anteriormente, o utilizar un puntero multidimensional como se muestra aquí.

Conclusión

Los punteros y matrices están estrechamente relacionados en C. El uso de índices y punteros para acceder al contenido de una matriz son simplemente dos lados de la misma moneda. Ofrecen dos perspectivas que apuntan hacia el mismo objetivo. Con la aritmética de punteros (que cubrimos en el artículo sobre punteros), puede acceder a cada elemento de la matriz uno tras otro o aleatoriamente. Con la indexación de matriz puede especificar un número de mano breve que es más fácil de entender y leer, pero que hace lo mismo. Esto es posible porque las matrices están dispuestas en la memoria en un bloque continuo de datos. El uso de la aritmética del puntero para acceder a las matrices a menudo se emplea en muchos programas profesionales de C como una forma de aumentar el rendimiento y como una forma de trabajar con las estructuras de datos de formas más genéricas.

NOTA: El compilador de C no verifica si sus punteros o índices de matriz son realmente válidos. Es un programa C perfectamente válido que puede indexar fuera del tamaño de una matriz, o mover un puntero fuera de una matriz existente. Esto causará un comportamiento desconocido y escribirá o leerá desde puntos aleatorios en la memoria. Esto a menudo puede causar resultados desastrosos. Depende del programador asegurarse de que todos sus punteros y matrices estén sujetos a su tamaño apropiado antes de leer o escribir datos.

Este artículo es parte de una serie – Cómo programar cualquier cosa: Programación C

Si usted aprecia este artículo usted puede ser que considere el apoyar de mi Patreon.

Pero si un compromiso mensual es un poco más, lo entiendo, podría considerar comprarme un café.

photo credit: Owen Signalman Lowestoft via photopin (license)

También te podría gustar...

Deja un comentario

A %d blogueros les gusta esto: