Pages - Menu

jueves, 6 de junio de 2013

Curso básico de C 8/10: Punteros

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.

Punteros en C
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.

¿Qué ventajas ves en el manejo de punteros?¿Qué complicación encuentras a la hora de trabajar con ellos?