Apuntadores: declaración, aritmética, operador de dirección y operador de referencia
Introducción
Bienvenida o Bienvenido a una de las clases más interesantes de Programación Básica. Al transitarla podrás comprender y manipular uno de los dos recursos principales de todo equipo de cómputo, la memoria. El objetivo de esta clase es conocer qué es un apuntador y su importancia en programación, cuáles son sus elementos, y cómo implementarlos en el lenguaje de programación C. Para lograrlo mantén tu mente abierta para imaginar el funcionamiento interno de una computadora, ya que los apuntadores son conceptos abstractos. Sin más, ¡comencemos!
Desarrollo del tema
¿Qué es un apuntador?
En pocas palabras es una variable que guarda una dirección de memoria.
Para comprender a profundidad esta definición, veamos cómo se forma una variable. La siguiente figura muestra sus cuatro elementos: identificador, valor, tipo de dato y dirección de memoria.
En la figura se define una variable entera inicializada con el valor de 5 en el lenguaje C, para lo cual usamos la instrucción int x = 5; Esta instrucción realiza múltiples acciones dentro de nuestra computadora que se describen a continuación. La primera acción consiste en solicitar al compilador que reserve un espacio en la memoria para almacenar una variable de tipo entero. En C este espacio se mide en bytes y para un tipo entero equivale a 4 bytes. Podemos imaginar que la variable es una caja y que la memoria es un estante donde podemos colocar múltiples cajas. Sin embargo, para usar el estante debemos reservar un espacio previamente. Este espacio se reserva cada vez que definimos una variable con su tipo de dato, en la figura se tienen 3 espacios reservados para las variables char c, int x, y float y.
La segunda acción que se realiza al lanzar la instrucción int x = 5; es asignar una dirección de memoria al espacio recién reservado para la variable x. Dicha dirección consiste en un número hexadecimal y puede recuperarse en el lenguaje C mediante el operador ampersand (&). Para mostrarlo en pantalla debemos usar un operador de formato especial, el %p. De esta forma, para averiguar qué dirección de memoria fue asignada a la variable x de nuestro ejemplo, podríamos usar la siguiente instrucción en C.
printf(“ La dirección de memoria de la variable x es %p ”, &x);
La última acción que realiza la instrucción int x = 5; es ordenar al compilador que asocie el identificador x a la variable, de forma que al usar este nombre podamos recuperar el valor que guarda en ese momento. El valor sería entonces, siguiendo nuestra analogía, lo que depositamos dentro de nuestra caja. Al hacer una reasignación, por ejemplo con la instrucción x=8; el contenido de la caja cambiaría al vaciar el 5 que teníamos previamente y depositar el valor actual de 8.
Habiendo recordado los elementos de una variable, podemos ahora ilustrar los elementos de un apuntador. Por favor analice la siguiente figura.
En la figura se observa que para definir un apuntador se coloca un * entre el tipo de dato (int) y el identificador (px, la p hace referencia a la palabra “pointer”, apuntador). A diferencia de una variable normal, el apuntador guarda como valor una dirección de memoria. Por este motivo, usamos el operador &, seguido del nombre de la variable de la que deseamos conocer su dirección. Los apuntadores son entonces variables que guardan direcciones de memoria. Practiquemos con la creación de un apuntador en el lenguaje C. Para esto, siga las instrucciones del programa que se muestra en la siguiente figura.
En la línea 6 definimos nuestra variable entera x y mostramos su valor en la línea 9. La línea 12 define un apuntador a entero que guarda la dirección de memoria de la variable x. En la línea 15 mostramos la dirección de memoria almacenada en el apuntador px, usando el operador %p. Finalmente, la línea 18 muestra que al igual que las variables tradicionales, los apuntadores no sólo guardan una dirección de memoria, sino que tienen a su vez una dirección de memoria que nos permite ubicarlos y manipularlos. Para obtener el valor contenido en la dirección que guarda el apuntador se utiliza un operador especial *px, el * seguido el nombre de un apuntador. A esta forma de obtener valores se llama derreferenciación.
Sí, una dirección de memoria, que al visitarla guarda otra dirección de memoria. En nuestra analogía del estante, es como si tuviésemos una caja que dentro no guarda un valor, sino la dirección de otra caja. En esta segunda podríamos encontrar ahora sí un valor o una nueva dirección de memoria. Esta forma de referenciar de una dirección a otra es útil para la formación de múltiples estructuras de datos como listas enlazadas, árboles, etc. El concepto de apuntador es uno de los más importantes en programación, pero también uno de los más complejos, por lo cual no debemos preocuparnos si cuesta trabajo comprender este concepto abstracto en la primera aproximación. La práctica será la clave para entenderlo a la perfección. Así que te invitamos a mantener tu mente abierta y consultar las referencias sugeridas para complementar el tema.
Conclusión
Los apuntadores son variables que guardan direcciones de memoria
En el lenguaje C:
- Definimos un apuntador con la sintaxis <<tipo de dato>> * <<nombre del apuntador>>
- Utilizamos el operador & para recuperar las direcciones de memoria de una variable
- Mostramos una dirección de memoria en hexadecimal mediante el formato %p dentro de printf
Podemos formar estructuras de datos como listas enlazadas o árboles mediante el direccionamiento de apuntadores.
Fuentes de información
- Video con curso sobre apuntadores en C y C++ (en inglés) https://www.youtube.com/watch?v=zuegQmMdy8M
- Fragmentos de libro en línea. https://www.google.com.mx/books/edition/Aprendiendo_C_en_24_Horas/o0TAvSRhXKcC?hl=es-419&gbpv=1&dq=apuntadores+en+C&pg=PA6&printsec=frontcover
- Declaración de apuntadores en C. https://learn.microsoft.com/es-es/cpp/c-language/pointer-declarations?view=msvc-170