You are on page 1of 8

U.T.

13: PUNTEROS
CONCEPTO DE PUNTERO:
Un puntero es bsicamente la direccin de un objeto. Es decir: Un puntero es una variable que guarda la direccin de memoria de otro objeto. Declaracin de punteros Las variables puntero tienen que declararse como tales. La forma general de este tipo de declaracin es: tipo Donde: tipo: es el tipo base del puntero, es decir, el tipo del objeto al que puede apuntar el puntero y es cualquier tipo vlido de C. * : indica a la computadora que se est creando una variable puntero. Nombre_variable: es el nombre de la variable puntero. Por ejemplo, si una variable p contiene la direccin de otra variable q, se dice que p apunta a q. Por eso, si q estuviese en la posicin 100 de memoria, entonces p tendra el valor 100. As, la declaracin de p, variable puntero, sera: int *p . Esta sentencia crea un puntero a un entero. Para un puntero a float, sera: float *p; *nombre_variable

OPERADORES ESPECIALES DE PUNTERO


En C existen dos operadores especiales que se usan en punteros: * y &. - Operador & : Operador monario que devuelve la direccin de memoria de la variable a la que precede. Por ejemplo, con : p: variable que apunta a q q: variable que est en la posicin 100 de memoria. La expresin: &q, devuelve 100, porque la direccin de la variable q es 100. - Operador * : Operador monario que devuelve el valor almacenado en la direccin a la que precede (el operador de puntero * no guarda ninguna relacin con el operador de multiplicacin, que utiliza el mismo smbolo). Por ejemplo, a partir de p y q del ejemplo anterior y siendo q=10, la expresin *p devuelve 10, porque el contenido de la direccin a la que apunta, es decir, el valor almacenado en la posicin 100 es 10.

As ser: q int q; int *p; q=10; &q 100 *p 10 y si p = &q p = 100 Por ejemplo, un breve programa: #include <stdio.h> main() { int *a, b; b=100; /* asignar 100 a b */ a=&b; /* asignar la direccin de b a la variable a */ printf (%d, *a); /* mostrar el valor de b utilizando un puntero */ /* printf() para mostrar direccin de memoria contenida en un puntero necesita utilizar el especificador de formato %p */ } Este programa imprime 100 en la pantalla. Es decir; imprime el valor que hay en la direccin de b, que es 100. Cuando el valor de una variable se referencia a travs de un puntero, al proceso se le llama indireccin. Por ejemplo: #include <stdio.h> main() { int *a, b; a = &b; /* asignar la direccin de b */ *a = 200; /* asignar a b un valor utilizando un puntero */ printf (el valor de b es %d, b); } Este programa obtiene 200 en la pantalla. p 100 10 100

EL TIPO BASE ES MUY IMPORTANTE


Aunque C permite que cualquier puntero apunte a cualquier lugar de memoria, el tipo de base es lo que determina cmo se tratar al objeto apuntado. Para entender la importancia de sto, considere el siguiente fragmento: int q; float *p; p = &q; /* qu hace esta lnea ? */ *p = 100,23 ;

Aunque no sea incorrecto sintcticamente, el fragmento est mal. Al puntero p se le asigna la direccin de un entero. Esta direccin se utiliza despus al lado izquierdo de una sentencia de asignacin para asignar un valor en un punto flotante. Sin embargo, los int son ms pequeos de los float, y esta sentencia de asignacin hace que se sobrescriba la memoria adyacente a q. Es decir, suponiendo int de 2 bytes y flota de 4 bytes, la sentencia de asignacin utiliza los dos bytes asignados a q as como dos bytes adyacentes, que ser probablemente donde est almacenado p, provocando de este modo un error. En general, el compilador de C utiliza el tipo de base para determinar cuntos bytes hay en el objeto al que apunta el puntero. As es como sabe C cuntos bytes ha de copiar cuando se hace una asignacin indirecta, o cuntos bytes comparar cuando se hace una comparacin indirecta. Por eso, es muy importante que se utilice el tipo de base apropiado para un puntero. No se debe utilizar nunca un puntero de un tipo para apuntar a un objeto de tipo distinto.

INICIALIZACIN DE PUNTEROS
Si se intenta utilizar un puntero antes de asignarle la direccin de una variable, ste contendr un valor desconocido y probablemente se producir un fallo en el programa. Esto se debe a que la declaracin de una variable puntero simplemente crea una variable capaz de contener una direccin de memoria y, no proporciona ningn valor significativo inicial. Por ejemplo, el siguiente fragmento sera incorrecto: main() { int *p; *p = 10; /*incorrecto: p no est apuntando a nada*/ El puntero p no est apuntando a ningn objeto conocido. De ah que intentar asignar un valor indirectamente utilizando p es peligroso y no tiene sentido. Si se inicializa una variable puntero asignndole una direccin de otra variable (recordar: la variable debe estar previamente declarada en el programa), por ejemplo con las siguientes declaraciones: float v; float *pv = &v; sera equivalente a: float v; float *pv;

En general, no tiene sentido asignar un valor entero a una variable puntero. Pero una excepcin es la asignacin de 0, ya que del modo en que estn definidos los punteros en C, un puntero que contenga un valor nulo (0) se supone que no se utiliza y que no apunta a nada. En C, se supone por convenio que 0 es una direccin de memoria invlida. Sin embargo, el compilador an as permitir que se utilice un puntero nulo, generalmente con resultados desastrosos.

En tales condiciones, la prctica recomendada es definir una constante simblica NULL que represente el valor 0 y usar NULL en la asignacin al puntero. Esta prctica enfatiza el hecho de que la asignacin del cero representa una situacin especial. As: #define NULL 0 float v; float *pv = NULL;

ARITMTICA DE PUNTEROS
Slo existen cuatro operadores que se pueden aplicar a las variables puntero: +, -, ++, -. La aritmtica de punteros es distinta a la aritmtica normal porque se hace en relacin al tipo de base del puntero. Cada vez que se incrementa un puntero, apuntar al siguiente elemento, dependiendo de su tipo de base, a partir del que est apuntando actualmente; y cada vez que se decrementa, apunta a la posicin del elemento anterior de su tipo base. Por ejemplo, sea p1 un puntero a un entero con valor actual de 200. Despus de la expresin p1 ++;

p1 contiene 202, no 201, suponiendo que los enteros tienen una longitud de dos bytes. Cada vez que se incremente p1, apunta al siguiente entero. Por la misma regla, si p1 hubiera sido un puntero float (suponiendo floats de 4 bytes), entonces el valor resultante contenido en p1 habra sido 204. Lo mismo ocurre al decrementar. Por ejemplo, p1 --; hace que p1 tenga el valor 198, suponiendo que inicialmente era 200. Con punteros a caracteres s se parece a la aritmtica normal porque, en general, los caracteres son de 1 byte de longitud, y as aumentan o decrecen de uno en uno. No se est limitando a los operadores de incremento o decremento. Se pueden sumar o restar enteros a/y de punteros. La expresin: p1 = p1+3; hace que p1 apunte al tercer elemento del tipo p1 a partir del que est apuntando actualmente. No se puede ejecutar otras operaciones aritmticas con punteros: no se puede multiplicar, dividir, sumar o restar punteros o sacar el mdulo de un puntero (sin embargo, se puede restar un puntero de otro hallando el nmero de elementos que los separa), no se les puede aplicar los desplazamientos de bits ni los operadores lgicos; y no se pueden sumar tipos float o double a los punteros.

Se pueden aplicar los operadores de incremento y decremento bien al propio puntero o al objeto al que apunta. Sin embargo, se debe tener cuidado cuando se intenta incrementar el objeto al que apunta un puntero. Por ejemplo, suponiendo que p apunta a un entero que contiene el valor 1, Qu piensa que har la siguiente sentencia? *p ++; Al contrario de lo que pudiera pensar, esta sentencia primero incrementa p y despus obtiene el valor de la nueva posicin. Para incrementar a lo que el puntero apunta, se debe hacer de la forma: (*p) ++; El parntesis hace que se incremente el valor al que apunta p. Suponiendo que las posiciones de memoria ocupadas por las variables son las siguientes: Nombre variable Valor Posicin en la memoria v1 11 1000 v2 1002 direc 1004 Qu hacen las instrucciones del siguiente programa? void main() { int v1, v2; int *direc; /* direc almacena la direccin en la que est almacenado un entero*/ v1 = 11; direc =&v1; v2 = *direc; } direc = &v1 direc tomar el valor 1000 que es la direccin en la que est almacenada la variable v1. v2 = *direc hace que v2 tome el valor 11 que es el contenido de la direccin almacenada en direc.

COMPARACIN ENTRE PUNTEROS


Se pueden comparar dos punteros utilizando operadores relacionales. Sin embargo, las comparaciones de punteros slo tienen sentido si los punteros se relacionan entra s si ambos apuntan a las variables relacionadas, como elementos del mismo array, por ejemplo.

UTILIZACIN DE PUNTEROS CON ARRAYS


En C existe una estrecha relacin entre los punteros y los arrays. De hecho, a menudo son intercambiables. Esta relacin entre los dos es la que hace que su implementacin sea nica y potente. Cuando se utiliza un nombre de array sin ndice, se est generando un puntero al principio del array, por lo que, se puede asignar ese valor a otro puntero y acceder al array utilizando aritmtica de punteros. Por ejemplo, el siguiente programa: #include<stdio.h> int a[4]={1, 2, 3, 4}; main() { int *p; p = a; /*asignar a p la direccin del principio de a*/ /*esto imprime los elementos primero, segundo, y tercero de a*/ printf ("%d %d %d \n", *p, *(p + 1), *(p + 2)); /*esto imprime lo mismo utilizando a*/ printf ("%d %d %d", a[0], a[1], a[2]); } Aqu, ambas sentencias printf () imprimen lo mismo. Los parntesis en expresiones del tipo *(p + 2) son necesarios, ya que * tiene una prioridad ms alta que el operador +. De ah que la aritmtica de punteros se haga en relacin al tipo base; permite que arrays y punteros se relacionen entre s. Para utilizar un puntero como medio de acceso a arrays multidimensionales, se debe hacer manualmente lo que el compilador hace de forma automtica. Por ejemplo, en este array: float balance[10][5]; cada fila tiene cinco elementos de longitud. Por tanto, para acceder a balance[3][1] (suponiendo que p es un puntero float) se debe utilizar un fragmento como ste: *(p + (3 * 5) + 1) Para alcanzar el elemento deseado, se debe multiplicar el nmero de fila por el nmero de elementos de la fila y despus sumar el nmero del elemento dentro de la fila. Normalmente, con arrays multidimensionales es ms sencillo utilizar indizacin de arrays que aritmtica de punteros pero, en general, es ms rpida la utilizacin de aritmtica de punteros que la indizacin de arrays. Un compilador de C crear un cdigo ejecutable ms rpido para una expresin como *( p + 3 ) que para el ndice de array comparable ser p[3] ;

As, se puede acceder a los elementos del array mediante aritmtica de punteros. Por ejemplo; #include<stdio.h> main() { char str[80]; *(str+3)="c"; printf ("%c", *(str+3)); } En este programa es perfectamente vlido e imprime c en la pantalla. Sin embargo, no se puede modificar el valor del puntero que se ha generado utilizando un nombre de array. Por ejemplo, suponiendo el programa anterior, sta es una sentencia incorrecta: str ++; Se debe pensar en el puntero que genera str como una constante que siempre apunta al principio del array. Por eso, no es vlido y el compilador informar de un error.

UTILIZACIN DE PUNTEROS A CONSTANTES DE CADENA


En C, cuando el compilador encuentra una constante de cadena encerrada entre dobles comillas en un programa, la almacena en la tabla de caracteres del programa y genera un puntero a la cadena. Por ejemplo, este programa es correcto e imprime estoy aprendiendo punteros en pantalla: #include<stdio.h> main() { char *p; p = "estoy aprendiendo punteros"; printf (p); } Veamos cmo funciona este programa: Se declara p como un puntero a carcter, as puede apuntar a un array de caracteres. Se almacena la cadena en la tabla de cadenas del programa, y asigna a p su direccin. Se imprime la cadena. De una forma ms eficiente, el programa sera: #include<stdio.h> char *p = "estoy aprendiendo punteros"; main() { printf (p); } Se inicializa p para que apunte a la cadena.

ACTIVIDADES
1. Escribir un programa que cree tres punteros y los inicialice de modo que cada uno de ellos apunte a cada una de las siguientes cadenas: uno, dos y tres, respectivamente. Y que despus imprima las 6 permutaciones posibles de estas tres cadenas ( por ejemplo, una dos tres, dos uno tres,) 2. Escribir un programa que no pare de leer cadenas hasta que se introduzca stop.

You might also like