5.1 INTRODUCCION
Un puntero es una variable (que apunta a otra variable) que guarda la direccin en memoria de otra variable, hasta el momento las variables que se han manejado guardan datos de tipo entero, carcter o flotante, pero ninguna de estas variables, guarda el valor de una direccin en memoria. La utilizacin de punteros en la elaboracin de programas hace que estos sean ms eficientes, adems que se puede utilizar lo que se conoce comomemoria dinmica.
Direccin en memoria:
Por ejemplo:
int x=10;
10
0XFF3
printf(%d,x);
printf(%p,&x);
Concepto de puntero:
La definicin de puntero ya se menciono anteriormente, este es una variable que guarda la direccin en memoria de otra. Cuando una variable se declara el compilador de C establece un rea de memoria para almacenar el contenido de la variable, esto de acuerdo al tipo de dato que se manejar por ejemplo si es de tipo entero se reservan 2 bytes, si es de tipo flota se reservan 4 bytes y as sucesivamente. Esto se hace en una direccin especifica de memoria a la cual se puede accesar con ya sabemos (por medio de el nombre de la variable), pero adems podemos tener acceso a esta variable por medio de un puntero el cual tiene acceso a su direccin de memoria y adems de proporcionarnos su direccin de memoria tambin puede modificar o mostrar el valor que esta contiene por medio de indireccin (manipulacin de el valor de una variable por medio de un puntero).
Un puntero es una variable como cualquier otra. Una variable puntero contiene una direccin que apunta a otra posicin en memoria. En esa posicin se almacenan los datos a los que apunta el puntero. Un puntero apunta a una variable en memoria.
Declaracin de punteros:
El puntero se declara igual que cualquier otra variable, solo que sabemos que este guardar la direccin en memoria de una variable cualesquiera que tambin fue declarada, por lo que para declarar un puntero antes debemos de saber a que tipo de variable va a apuntar. Si la variable es de tipo int el puntero ser declarado de tipo int, si la variable es de tipo float el puntero se declarado de tipo float, etc.
Ejemplos:
El operador * en una declaracin indica que la variable declarada almacenar una direccin de un tipo de dato especificado, por lo que siempre que en una declaracin aparezca un * esta ser un puntero.
Inicializacin de punteros:
Al igual que otras variables, C no inicializa los punteros cuando se declaran y es preciso inicializarlos antes de su uso. La inicializacin de un puntero proporciona a ese puntero la direccin del dato correspondiente. Despus de la inicializacin, se puede utilizar el puntero para referenciar los datos direccionados. Para asignar una direccin de memoria a un puntero se utiliza el operador de referencia &. As por ejemplo:
&valor significa la direccin de valor . Por lo tanto, el mtodo de inicializacin tambin denominado esttico
Asignar memoria definiendo una variable y a continuacin hacer que el puntero apunte al valor de la variable:
int x; //Declaracin de la variable x int *p; //Declaracin del puntero p=&x; //puntero p apuntando a x
Indireccin:
Manejar por medio de un puntero la direccin en memoria de una variable, por ejemplo; si se quiere asignar un valor a x por medio del puntero *p: se escribira: *p=valor; De tal manera que siempre que queramos accesar al valor de nuestra variable por medio del puntero que apunta a ella, antepondremos un * al puntero.
Operador & * *
Propsito Obtiene la direccin de una variable Define una variable como puntero Obtiene el contenido de una variable puntero
Cuando una funcin debe modificar el valor del parmetro pasado y devolver este valor modificado a la funcin que lo llama, se tiene que pasar el parmetro por referencia. En este mtodo el compilador pasa la direccin de memoria del valor del parmetro a la funcin. Cuando se modifica el valor del parmetro (la variable local), este valor queda almacenado en la misma direccin de memoria, por lo que al retornar a la funcin llamadora la direccin de la memoria donde se almacen el parmetro contendr el valor modificado. Para pasar una variable por referencia, el smbolo & debe preceder al nombre de la variable y el parmetro variable correspondiente de la funcin debe declararse como puntero.
C permite utilizar punteros para implementar parmetros por referencia, ya que por defecto en C el paso de parmetros es por valor.
void intercambio (int *a, int *b) { int aux=*a; *a=*b; *b=aux; }
En la llamada siguiente, la funcin intercambio() utiliza las expresiones *a y *b para acceder a los enteros referenciados por las direcciones de las variables i y j:
int i=3, j=50; printf(i = %d y j = %d \n, i,,j); intercambio (&i,&j); printf(i = %d y j = %d \n, i,,j);
La llamada a la funcin intercambio() debe pasar las direcciones de las variables intercambiadas. El operador & delante de una variable significa <<dame la direccin de la variable>>.
Una variable, o parmetro puntero se declara posicionando el asterisco (*) antes del nombre de la variable. Las variables p, r y q son punteros a distintos tipos.
5.5 Expresiones de apuntadores y aritmtica de apuntadores. Al contario que un nombre de arreglo, que es un puntero constante y no se puede modificar, un puntero es una variable que se puede modificar. Como consecuencia, se puede realizar ciertas operaciones aritmticas sobre punteros.
A puntero se le puede sumar o restar un entero n; esto hace que apunte n posiciones adelante, o atrs de la actual. Una variable puntero puede modificarse para que contenga una direccin de memoria n posiciones adelante o atrs. Por ejemplo:
int v[10]; int *p; p =v; (v+4); /* apunta al 5 elemento */ p=p+6; /8 contiene la direccin del elemento 7 */
A una variable puntero se le puede aplicar el operador ++, o el operador --. Esto hace que contenga la direccin del siguiente, o anterior elemento. Por ejemplo:
float m[20]; float *r; r=m; r++ /* contiene la direccin del elemento siguiente */
Recuerde que un puntero es una direccin, por consiguiente, slo aquellas operaciones de <<sentido comn>> son legales. No tiene sentido, por ejemplo, sumar o restar una constante de coma flotante.
No se pueden sumar dos punteros. No se pueden multiplicar dos punteros. No se pueden dividir dos punteros.
Se puede utilizar esta tcnica para explorar cada elemento de alfabeto sin utilizar una variable de ndice. Un ejemplo puede ser: p =&alfabeto[0]; for (i=0; i<strlen(alfabeto); i++) { printf (%c,*p);
p=p+1; }
Los arreglos y punteros estn fuertemente relacionados en el lenguaje C. Se pueden direccionar arreglos como si fueran punteros y punteros como si fueran arreglos. La posibilidad de alamacenar y acceder a punteros y arreglos, implica que se pueden almacenar cadenas de datos en elementos de arrays. Sin punteros eso no es posible, ya que no existe el tipo de dato cadena (string) en c. No existen variables de cadena, nicamente constantes de cadena.
Un nombre de un arreglo es simplemente un apuntador. Supongamos que se tiene la siguiente declaracin de un array:
lista
[0]
Memoria 10
Lista
20 30 40 50
Si se manda visualizar lista[0] se ver 10. Pero que sucede si se visualiza *lista? Como el nombre de un arreglo es un puntero, tambin se ver 10. Esto significa que:
Lista +0 apunta a lista[0] Lista +1 apunta a lista[1] Lista +2 apunta a lista[2] Lista +3 apunta a lista[3] Lista +4 apunta a lista[4]
Por lo que, para imprimir, almacenar o calcular un elemento de un arreglo, se puede utilizar notacin de subndices o de punteros. Dado que un nombre de un arreglo contiene la direccin del primer elemento del arreglo, se debe indireccionar el puntero para obtener el valor del elemento. El nombre de un arreglo es un puntero, contiene la direccin en memoria de comienzo de la secuencia de elementos que forma el arreglo. Es un puntero
constante ya que no se puede modificar, slo se puede acceder para indexar a los elementos del arreglo. En el ejemplo se pone de manifiesto operaciones correctas y errneas con nombres de arreglo.
/* Se indexa a partir de v */ for (j=0;j<10;j++) (v+j)= j10.0; p = v+4 /* se le asigna la direccin del 4to. Elemento */ v = &x; /* error: intento de modificar un puntero constante */
Punteros de cadenas
Los punteros se pueden utilizar en lugar de ndice de arreglos. Considrese la siguiente declaracin de un arreglo de caracteres que contiene las veintisis letras del alfabeto internacional (no se considera la ). char alfabeto[27] = ABCDEFGHIJKLMNOPQRSTUVWXYZ;
char *p;
p= &alfabeto[0];
p=alfabeto;
printf(%c\n, *p);
p= &alfabeto[15];
de modo que p apuntar al carcter 16 (la letra Q). Sin embargo, no se puede hacer
p = &alfabeto;
ya que alfabeto es un arreglo cuyos elemntos son de tipo char, y se producira un error al compilar (tipo de asignacin es incompatible).
char cadena1[ ]=Hola viejo mundo; /* Arreglo contiene una cadena */ char cptr = C a su alacance ; / puntero a cadena, el sistema reserva memoria para la cadena */
El siguiente programa implementa una funcin para contar el nmero de caracteres de una cadena. En el primero programa, la cadena se describe utilizando un arreglo, y en el segundo, se describe utilizando un puntero.
main()
{ char cad [ ] = Universidad Autonoma de Baja California ; printf(La longitud de %s es %d caracteres \n, cad, longitud(cad)); }
int longitud (char cad[ ]) { int pos=0; while (cad[pos]) { pos++; } return pos; }
El Segundo programa utiliza un puntero para la funcin que cuenta los caracteres de la cadena. Adems, utiliza la aritmtica de punteros para indexar los caracteres. El bucle termina cuando llega al ltimo carcter, que es el delimitador de una cadana: \0.
#include <stdio.h>
main() { char cad [ ] = Universidad Autnoma de Baja California ; printf(La longitud de %s es %d caracteres \n, cad, longitud(cad)); }
int longitud (char cad[ ]) { int cuenta=0; while (*cad++) { cuenta++; } return cuenta; }