Vamos entrando en la recta final del curso básico de C, durante éste tiempo
hemos estado viendo todas las operativas básicas para desarrollar programas
básicos en C. A lo largo de éste artículo iremos viendo otro concepto
bastante importante, los punteros.
Foto tomada de freedigitalphotos.net |
Lo primero y principal que tenemos que saber es:
¿Qué es un puntero?
Un puntero es una variable estática que almacena una dirección de memoria,
en esa dirección estará recogido un valor de un determinado tipo de datos.
Declaración de un puntero.
En el capítulo que dediqué a procedimientos y funciones ya se pudo ver un
poco el tema de los punteros ya que es esencial para el paso de parámetros por
referencia, es gracias al paso de estos punteros por lo que pudimos modificar
el valor de los parámetros.
Un puntero se declara de la siguiente forma:
Tipo *especificador;
Por ejemplo:
int *num;
char *c;
double *num2;
De ésta forma definimos un puntero que sólo podrá apuntar a direcciones de
memoria que contengan el tipo de dato declarado, en el ejemplo
anterior estaríamos declarando punteros que sólo apunten a enteros, caracteres
y reales respectivamente.
Operadores propios de punteros.
El operador & me da la dirección de memoria a la que está apuntando el
puntero.
El operador * me da el contenido almacenado en la dirección de memoria a la
que apunta el puntero.
Hemos estado utilizando punteros desde el principio.
Realmente si nos paramos a pensar, hemos utilizado punteros desde el
principio del curso, concretamente desde que comenzamos a utilizar la instrucción scanf, si recordamos un ejemplo cualquiera:
scanf(“%d”,&num);
No estamos mandando como argumento la variable en sí, sino el puntero que
apunta a dicha variable, de tal forma que al leer el valor por teclado estamos
introduciendo unos datos que se almacenan en esa dirección de memoria. En
palabras humanas podemos llamarlo “Lee por teclado y almacena en ésta
dirección” o similares.
Variables y asociación de punteros.
Cuando declaramos un puntero éste no apunta realmente a nada, debemos
especificar a qué dirección debe apuntar para poder trabajar con él. Podemos
hacerlo de la siguiente forma:
int *num;
int num1;
num=&num1;
A partir de ahora el puntero num apuntara a la dirección de memoria donde se
encuentra el valor de la variable num1. De ésta forma ya están ligados el
puntero y la variable.
Modificar el contenido al que apunta un puntero.
Podemos trabajar con el valor al que apunta un puntero mediante
el operador *. Gracias a esto podemos usar todos los operadores que hemos visto hasta ahora (suma, resta, etc.) en
función del tipo de variable.
En el ejemplo anterior sería:
int *num;
int num1;
num=&num1;
*num=1;
Una cosa importante que se debe tener en cuenta es que si se modifica el
contenido al que apunta un puntero, estamos modificando el valor de esa
variable. Veámoslo en un pequeño ejemplo:
#include <stdio.h>
int main ( void )
{
int *num;
int num1;
num1=10;
num=&num1;
*num=5;
printf ("%d\n\n",num1);
system("PAUSE");
return 0;
}
El programa mostrará por pantalla el número 5 en vez del 10, esto es debido
a que al haber modificado el contenido de la celda donde apunta el puntero (es
decir, la variable num1) estamos modificando el contenido de la misma, o sea,
el contenido de la variable num1.
Recuerda, esto es importante: Si modificamos el valor de la celda de
memoria donde apunta el puntero, estamos modificando el valor de la variable.
Un ejemplo más para poder verlo:
#include <stdio.h>
int main ( void )
{
int x, *px;
x = 12;
printf ("Valor de x %d, de
ip %d", x, px);
px = &x;
*px = *px + 5;
printf ("\nValor de x %d,
de *px %d x de px %d", x, *px, px);
x = *px + 10;
printf ("\nValor de x %d,
de *px %d", x, *px);
*px += 1;
printf ("\nValor de x %d,
de *px %d\n\n", x, *px);
system("PAUSE");
return 0;
}
Como se puede comprobar, da igual el elemento que modifiquemos, si la variable o el
contenido de la dirección a la que apunta el puntero. En cuanto un puntero y
una variable estén ligados, la modificación del contenido afecta a ambos.
Modificar la dirección de un puntero.
Un puntero puede cambiar de dirección perfectamente, para realizar esto tan
sólo debemos asignarle otra dirección de memoria a la que apuntar.
#include <stdio.h>
int main ( void )
{
int x, y, *px;
x = 12;
y = 7;
px = &x;
printf ("Valor de x %d, de
y %d y de *px %d\n", x, y, *px);
px = &y;
printf ("Valor de x %d, de
y %d y de *px %d\n", x, y, *px);
system("PAUSE");
return 0;
}
Conclusión.
Con esto terminamos el octavo capítulo del curso básico de C. Hemos visto
el concepto básico de un puntero, su forma de utilizarlo y de operar con el
contenido en memoria al que apunta así como la forma en que afecta a la
variable ligada.
Un puntero se puede utilizar prácticamente para todo, se pueden realizar
experimentos como declarar arrays de punteros, o punteros a arrays, punteros a
cadenas de caracteres, etc.
Es recomendable ver y realizar los ejercicios de procedimientos yfunciones, ya que gracias a éstos podrás asimilar los conceptos de punteros
perfectamente, es importante de cara al siguiente capítulo.
En el siguiente capítulo entraremos de lleno en un concepto que por lo
general suele ser complicado de asimilar la primera vez: las listas enlazadas
dinámicamente, o simplemente listas. También veremos el concepto de pilas,
colas y si es posible, árboles.