Uno de los problemas más comunes a los que se enfrentan los usuarios que empiezan a programar en C o C++, es el uso de los punteros.
¿Qué es un puntero?
Un puntero no es más que una variable, en la cual se almacena una dirección de memoria. Esto parece muy simple, pero luego da muchos quebraderos de cabeza. Al ser una dirección de memoria, le podemos decir a un puntero que en ese lugar donde apunta queremos almacenar un valor, por ejemplo un número.
Para realizar una explicación muy sencilla, vamos a decir que un puntero es como un buzón de correos y nuestra memoria RAM, es similar a una comunidad de vecinos donde hay muchos buzones. Además en esta comunidad en lugar de tener el nombre puesto en el buzón, cada uno va a tener un identificador único.
Como se puede ver en la imagen, hay muchos buzones (zonas de memoria), pero no todas las podemos usar, ya que hay buzones que son nuestros y otros que son de otros vecinos (otros programas).
El buzón b5 tiene un papel con el número 23 escrito (en esa posición identificada como b5 está almacenado el número 23).
El buzón b1 es un puntero, ya que lo que tiene almacenado (b5), no es un valor, sino un identificador de otro buzón (una dirección de memoria).
¿Cómo se usa un puntero?
Una vez que ya sabemos que es un puntero, una variable cuyo valor es una dirección de memoria, vamos a proceder a explicar cómo se utilizan.
Imaginamos que el cartero sabiendo que hay dos buzones nuestros, decide introducir un paquete (el valor 23) en uno de nuestros buzones. Pero se da cuenta de que lo introdujo en el buzón que no era, entonces se le ocurre dejarnos en el buzón correcto (b1), un papel donde pone “tu paquete está en b5“.
La manera de obtener el valor es bien sencilla, nosotros abriríamos b1, veríamos que lo que hay dentro es el papel y entonces diríamos, para alcanzar el valor, tengo que ir a b5 y obtener su contenido.
En la imagen superior se puede ver cómo funcionan realmente los punteros. El carácter * representa a un puntero en C. Si quieres aprender este lenguaje te recomiendo este curso de programación en C.
En la dirección de memoria 0x67 tenemos almacenado un 5. Podemos decir que la variable cuya dirección de memoria es 0x67 es un entero o dicho de otra manera, que tenemos un entero de valor 5 almacenado en 0x67.
En la dirección de memoria 0x75 tenemos almacenado otra dirección de memoria, la 0x67. En este caso tenemos un puntero a entero, ya que tenemos en 0x75 almacenada la dirección de memoria de un entero. Es importante recalcar que tenemos dónde está el entero, no cual es su valor.
De igual manera, en la dirección 0x88 tenemos almacenado otra dirección de memoria, pero en este caso no es un puntero a entero, ya que la dirección de memoria almacenada no es la de un entero sino la de un puntero a entero. Esto da como resultado que tenemos un puntero a puntero a entero.
Como veis es fácil generalizar su funcionamiento partiendo de este ejemplo.
Respecto al uso dentro de un programa, los punteros se usan ya que permiten realizar operaciones de manera más eficiente al trabajar con direcciones de memoria. Por ejemplo si tuviéramos que intercambiar el valor de dos cadenas de texto de 200bytes cada una, es mucho más eficiente cambiar los punteros a cada una de las cadenas (2 bytes, uno por puntero), que copiar el contenido. El tener que gestionar manualmente estos punteros, quizás hacen de C un lenguaje complejo para empezar a programar.
Ejemplo práctico
Muchos se preguntarán todo esto está muy bien, pero es cierto o me están engañando. Para ello os dejamos el siguiente programa en C, que os puede servir para afianzar vuestros conocimientos con los punteros.
#include <stdio.h>
#include <stdlib.h>
int main(){
int valor =5 ;
int *p;
int **pp;
p=&valor;
pp=&p;
printf("Contenido en memoria: %8d Direccion de memoria: %p Tipo de dato: int\n", valor, &valor );
printf("Contenido en memoria: %p Direccion de memoria: %p Tipo de dato: int*\n",p,&p);
printf("Contenido en memoria: %p Direccion de memoria: %p Tipo de dato: int**\n",pp,&pp);
printf("\n\nEl valor al que apunta mi puntero a entero es: %d",*p);
}
El resultado de la ejecución es: Contenido en memoria: 5
Direccion de memoria: 0x5fcaec Tipo de dato: int Contenido en memoria: 0x5fcaec
Direccion de memoria: 0x5fcae0 Tipo de dato: int* Contenido en memoria: 0x5fcae0
Direccion de memoria: 0x5fcad8 Tipo de dato: int** El valor al que apunta mi puntero a entero es: 5
Como podéis ver:
- Para declarar un puntero a entero se usa el asterisco: int *p
- Para obtener la dirección de memoria dónde esta una variable utilizamos el carácter &
- Para acceder al contenido de la dirección de memoria a la que apunta un puntero utilizamos el carácter * antecediéndolo al puntero.
Espero que este artículo os sea útil
Un saludo
Jorge Durán
Latest posts by Jorge Durán (see all)
- [Remix] Multitud de recursos para .NET - 18 junio, 2021
- ¿Qué es un puntero y cómo se usan? - 4 junio, 2021
- Los 10 mejores paquetes nuget que tienes que instalar - 26 abril, 2021
4 comentarios en “¿Qué es un puntero y cómo se usan?”
Fraciel Arevalo
magnifica esplicasion me atrvo a decir que de tantos tutoriales y esplicasiones esta es la que mas clara me a quedadado
Daniel R
Muchas gracias, muy bien explicado, muy agradecido, saludos!
David Arteaga
Me fue de mucha ayuda, muchas gracias.
Jhon Gesell Villanueva Portella
Hola muchas gracias por la entrada, siempre había oído hablar de los punteros en programación aunque en realidad no lo había pillado; un saludo desde Lima-Perú.