domingo, 25 de septiembre de 2011

Punteros C Parte 1

Como segunda entrada me gustaría hablar de los punteros en C. Los punteros son una parte importante y complicada desde el punto de vista de un estudiante. Es importante por su utilidad y la cantidad de ejercicios, practicas, etc. Para comenzar haré un breve resumen acerca del concepto de puntero pues esto es lo más sencillo, la dificultad comienza a la hora de trabajar con ellos.

Un puntero en C  es una variable que apunta a una dirección de memoria. Esta dirección apuntada puede tener información de distinto tipo ( ya sea int, char, float, struct ,incluso otro puntero).

Para poder declarar el puntero debemos saber a que tipo de dato hará referencia esta dirección de memoria. Además, a la hora de declararlo deberemos escribir un '*' junto al nombre de la variable de tipo puntero. Por lo tanto si deseamos un puntero que apunte a un entero lo declararemos: " int *puntAInt; ". Para acceder a la  memoria  simplemente deberemos acceder a "puntAInt", mientras que para acceder a los datos almacenados en esta dirección de memoria deberemos utilizar "*puntAInt". Si deseamos acceder a la dirección de memoria de una variable lo haremos con '&', es decir, si deseamos asignar a este puntero una variable llamada "unNumero" deberíamos hacer: "puntAInt = &unNumero". Es importante asignar una dirección de memoria valida a nuestro puntero, por ello la importancia de pasar la dirección mediante el '&' y una variable. Esto es así debido a que podemos realizar una violación de segmento accediendo a memoria que no pertenece a nuestro programa. También ocurrirá este tipo de fallo si no asignamos ninguna dirección de memoria al puntero, pues no sabemos a que dirección apunta inicialmente.
Todo esto se verá mejor con el siguiente ejemplo:

Podemos ver por ejemplo en la función dividir como por referencia accedemos al valor de las variables del main. Debido a que modificamos el valor de ellas accedemos con el '*'. Además hay que prestar especial atención en la función "leerint(int *a)" pues en ella al realizar la lectura del número ("scanf("%d",a);") vemos que el puntero no lleva '*' esto es debido a que en la utilización normal de scanf mandamos una dirección de memoria (ej: scanf("%d",&variable);), por tanto al escribir 'a' realmente estamos dando la dirección de memoria de la variable que hemos pasado como parámetro, por ello se modifica su valor con scanf. 

Hasta aquí no hay una dificultad excesiva. Sin embargo, a la hora de trabajar con struct la cosa cambia. Esto es debido a que si nosotros tenemos un "struct punto{int x; int y;};" y realizamos un puntero a esta struct: " struct punto unPunto; struct punto *puntero = &unPunto;" la forma de acceso a los datos no es tan simple. Para acceder a los valores 'x' 'y' de un punto mediante el puntero deberemos realizarlo de la siguiente manera: (*puntero).x  y  (*puntero).y. Mediante "(*puntero)" accedemos a la variable unPunto y ya a partir de hay al resto de miembros del punto. Por tanto a la hora de hacer una función de lectura por referencia de un struct la cosa cambia en relación al "leerint" anterior. Veamos un ejemplo de esto:

Como se puede apreciar en la función leerFraccion la forma de realizar scanf cambia. Esto es así debido a lo comentado antes. Para leer necesitamos la dirección de memoria de numerador por ello 1º el acceso a numerador por ello (*fracLec).numerador, además la  dirección de memoria por ello el '&' antes.

Aquí acaba la primera parte de estas pequeñas aclaraciones acerca de los punteros. Pronto realizare una segunda parte de punteros relacionada con la gestión dinámica de memoria. Si tenéis alguna duda, alguna mejora o queréis que hable de algún tema en especial lo podéis comentar. 

1 comentario:

  1. Muchas gracias por estas explicaciones amigo, la verdad que vas al grano y se entiende todo muy bien

    ResponderEliminar