jueves, marzo 13, 2008

Punteros en c

Punteros

Básicamente, un puntero a una variable indica la dirección de memoria en la que se almacena dicha variable. Podemos imaginar la memoria como un gran armario con muchos cajones numerados en los que guardamos hojitas de papel con números o letras. Pues bien, el puntero no hace referencia a lo que hay escrito en la hoja, sino al cajón en el que se encuentra.

2.1 Definición de punteros

Un puntero ha de definirse junto con el resto de datos, a la cabeza del archivo/función. Podemos crear punteros a un tipo de dato concreto anteponiendo un asterisco al nombre de la variable: tipo_dato *nombre_dato. Por ejemplo, int *suma crea una variable, suma, que es un puntero a un entero.

Cuando aparecen punteros de por medio la termnología puede resultar un poco liosa. Cuando hable de dirección de una variable me estaré refiriendo al valor que se guarda en la variable puntero, es decir, a una dirección de la memoria. Así, al referirme al valor de la variable estaré hablando al valor almacenado en esa dirección de memoria, es decir, a un entero, real, etc., dependiendo del tipo del que sea el puntero.

Como un puntero hace referencia a la dirección de los datos en memoria, para acceder a los propios datos hemos de indicar de alguna forma que queremos mirar lo que hay en el cajón (el valor que hay guardado en esa dirección). Para ello antepondremos, de nuevo, un asterisco al nombre.

Si resulta que queremos obtener la dirección de una variable que hemos creado de forma normal lo que haríamos no sería anteponer un asterisco, sino un ampersand (&).

Al igual que todas las variables al ser creadas, es muy probable que un puntero sólo contenga basura, es decir, la dirección de memoria puede no ser válida (de hecho, si no inicializamos un puntero es seguro que el programa hará cosas raras) o ser la de otra variable. Esto puede ocasionar fallos muy desagradables, como puede ser que al cambiar el valor de la variable nos cambie también otra que no tiene nada que ver con ella (a mí me ha pasado un montón de veces...).

Para asegurarnos de que apunta a una dirección de memoria válida hemos de hacer una llamada a la función malloc o calloc. Estas dos funciones lo que hacen es buscar memoria que esté libre y asignarla al puntero. De todas formas, el valor de la variable que se guarda en esa dirección también será basura, excepto si la varible puntero se inicializó con una llamada a calloc este valor será inicilalizado a 0 o la cadena vacía, dependiendo del tipo de dato. Para una mayor explicación de estas dos funciones ver un poco más abajo.

Como mi verborrea no resulta especialemente clara, aquí va un pequeño programa de ejemplo:

#include
#include /*Archivo de cabecera necesario, para malloc y calloc*/
void main(void)
{
int a, b, *suma; /* Creo 3 variables: a,b de tipo entero y suma, un
puntero a un entero*/
a=0;
b=1;
suma=malloc(sizeof(int));/*Aquí asignamos memoria libre al puntero*/
*suma=0; /* Le asigno 0 al valor al que apunta suma */
*suma=a+b; /* Ahora le asigno a+b */
printf("%d\n",*suma);
}

En el ejemplo anterior no sería válido escribir suma=a+b porque entonces estaríamos asignando 1 (a+b) a una dirección de memoria. Hay recursos para asignar direcciones de memoria (que explicaré más abajo), pero no debe hacerse, en principio, directamente.

No hay comentarios: