You are on page 1of 10

4/3/2014

Programacin en C/Punteros - Wikilibros

Programacin en C Punteros
De Wikilibros, la coleccin de libros de texto de contenido libre. Programacin en C/Punteros

Contenido
1 Concepto 2 Declarando punteros 3 Explicacin 4 Operadores 5 Operaciones Aritmticas 6 Punteros Constantes 7 Punteros Genericos 8 Punteros y Matrices 9 Punteros a cadenas de caracteres 10 Matrices de Punteros 11 Punteros a Punteros 12 Matrices de punteros a cadenas de caracteres 13 Ejemplos 13.1 Asignando valores a punteros

Concepto
Un puntero es una variable que contiene la direccin de memoria de un dato o de otra variable que contiene al dato. Quiere esto decir, que el puntero apunta al espacio fsico donde est el dato o la variable. Un puntero puede apuntar a un objeto de cualquier tipo, como por ejemplo, a una estructura o una funcin. Los punteros se pueden utilizar para referenciar y manipular estructuras de datos, para referenciar bloques de memoria asignados dinamicamente y para proveer el paso de argumentos por referencias en las llamadas a funciones. Muchas de las funciones estandares de C, trabajan con punteros, como es el caso del scanf o strcpy. Estas reciben o devuelve un valor que es un puntero. Por Ej. A scanf se le pasa la direccin de memoria del dato a leer (esto es un puntero)...

c h a ra ; s c a n f( " % c " , & a ) ;

Declarando punteros
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros 1/10

4/3/2014

Programacin en C/Punteros - Wikilibros

Ya se dijo que un puntero es una variable que guarda la direccin de memoria de otra variable, haciendo logica a esto, decimos que un puntero se declara igual que cualquier otra variable, pero anteponiendo un * (asterisco) antes del nombre de la variable. Su sintaxis seria: tipo *NombrePuntero; Donde tipo es el tipo de dato al que referenciar este puntero, es decir, que si se necesita guardar la direccin de memoria de un dato int, se necesita un puntero de tipo int.

Explicacin
Veamos el siguiente codigo:

# i n c l u d e< s t d i o . h > i n tm a i n ( ) { i n ta = 0 ;/ / D e c l a r a c i nd ev a r i a b l ee n t e r ad et i p oe n t e r o i n t* p u n t e r o ;/ / D e c l a r a c i nd ev a r i a b l ep u n t e r od et i p oe n t e r o p u n t e r o=& a ;/ / A s i g n a c i nd el ad i r e c c i nm e m o r i ad ea p r i n t f ( " E lv a l o rd eae s :% d .\ n E lv a l o rd e* p u n t e r oe s :% d .\ n " , a , * p u n t e r o ) ; p r i n t f ( " L ad i r e c c i o nd em e m o r i ad e* p u n t e r oe s :% p " , p u n t e r o ) ; r e t u r n0 ; }

Igual que cuando usamos un &, en la lectura de datos con scanf, igual de esta forma lo usamos aqu, tal vez te acordaras que decamos que las cadenas de caracteres (%s) no usaban este operador, esto es por que en una cadena de caracteres es un arreglo de caracteres, por lo que el primer carcter es la direccin de inicio de la cadena. El operador *, nos permite acceder al valor de la direccion del puntero, en este caso nos permite acceder al valor que continiene a. De esta forma "a" y "*puntero" muestran el mismo dato, pero esto no quiere decir que sea lo mismo, uno es un entero el otro un puntero. La impresin con %p, es para poder imprimir la direccin de memoria en valor hexadecimal (0x...), tambin podemos imprimir: ...%p",&a) y funciona de la misma forma, y es lgico que tanto a, como puntero tienen la misma direccin de memoria. Diferentes direcciones? Tal vez notaste que en cada ejecucin la direccin de memoria cambia, esto es por que es el sistema operativo es quien esta encargado de administrar la memoria y es este quien dice que espacios podra tomar el programa. Esto quiere decir que uno no puede asignarle una direccin de memoria a un puntero directamente , es decir yo no puedo hacer lo siguiente.

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros

2/10

4/3/2014

Programacin en C/Punteros - Wikilibros

i n t* p u n t e r o = 0 x b f c 5 b 1 c 8 ;

Esto no puedo ni debo hacerlo ya que yo no se que esta haciendo esta direccin de memoria, si el sistema la tiene o no disponible, etc... Pero si puedo hacer esto:

i n t* p u n t e r o = N U L L ;

NULL, es el espacio en memoria con direccin 0, esto quiere decir que existe, lo que significa que le asignamos una direccion valida al puntero, pero el valor que tiene NULL no se nos permite modificarlo, ya que pertenece al sistema.

Operadores
Ya anteriormente te poniamos algunos ejemplos de como asignar la direccin de memoria a un puntero y de como acceder al valor de este. Operador de Direccin (&): Este nos permite acceder a la direccion de memoria de una variable. Operador de Indireccion (*): Ademas de que nos permite declarar un tipo de dato puntero, tambin nos permite ver el VALOR que esta en la direccin asignada. Incrementos (++) y Decrementos (--): Te daras cuenta que puedes usar un puntero como si de un array se tratase, es por esto que permite estos operadores. De lo anterior podemos decir que: int a; Es Igual int *puntero=&a; printf("%d",a); Es Igual printf("%d",*puntero);

Operaciones Aritmticas
Un puntero nos permite sumar o restar nmeros enteros, pero su funcionamiento ahora es de posiciones, es decir nos permitir movernos a la siguiente direccin de memoria. A un puntero no se le puede realizar multiplicaciones, divisiones, sumas o restas con otro puntero o con un valor de tipo coma flotante (float, double...). Esto es por que un puntero no es un valor es una direccin. En un puntero se pueden realizar varias operaciones de tipo enteras, pero en dependencia de como se usen sus resultados pueden ser muy diferentes, a continuacin les muestro algunas de estas operaciones:

/ / D e f i n a m o se s t a sv a r i a b l e s : i n tx [ 1 0 0 ] , b , * p a , * p b ; / / . . . x [ 5 0 ] = 1 0 ;/ / L ea s i g n a m o se lv a l o rd e1 0 ,a la r r a y# 5 0 p a = & x [ 5 0 ] ;/ / L ea s i g n a m o sa lp u n t e r op a ,l ad i r e c c i o nd em e m o r i aq u et i e n ex [ 5 0 ]
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros 3/10

4/3/2014

Programacin en C/Punteros - Wikilibros

/ / A h o r am o s t r a m o sa l g u n a sp o s i b l e so p e r a c i o n e s : b=* p a + 1 ;/ / E s t oe sc o m od e c i re lv a l o rq u et i e n ee la r r a yd ex [ 5 0 ]s u m a r l e1 . / / E s t oe si g u a la :b = x [ 5 0 ] + 1 ;= >S uv a l o rs e r i ai g u a la1 1 . b=* ( p a + 1 ) ;/ / E s t op r i m e r op a s aal as i g u i e n t ed i r e c c i o nd em e m o r i ayl u e g ol or e f e r e n c i a / / E lr e s u l t a d oe s :b=x [ 5 1 ] ; p b=& x [ 1 0 ] ;/ / a lp u n t e r op bs el ea s i g n al ad i r e c c i o nd ex [ 1 0 ] * p b=0 ;/ / A lv a l o rq u et i e n ee lp u n t e r os el ea s i g n a0 / / E s t oe si g u a lq u ed e c i r :x [ 1 0 ]=0 * p b+ =2 ;/ / E lv a l o rd e lp u n t e r os ei n c r e m e n t ae nd o su n i d a d e s ,e sd e c i rx [ 1 0 ]=2 ( * p b ) ;/ / E lv a l o rd e lp u n t e r os ed e c r e m e n t ae nu n au n i d a d . x [ 0 ]=* p b ;/ / Ax [ 0 ]s el ep a s ae lv a l o rd ex [ 1 0 ]ye lp u n t e r op b ,p a s aaa p u n t a rax [ 9 ] / / r e c o r d a ,q u e-e sp o s t i n c r e m e n t o ,p r i m e r oa s i g n a r ayl u e g or e s t a r a .

Punteros Constantes
Es posible que hayas pensado como declarar un puntero como una constante, tal vez pensaste en un #define , o en un atributo const. Bueno es posible usar el atributo const, pero para un puntero hay que hacerlo de otra forma. FORMA ERRADA:

i n ta = 1 0 , b = 2 0 ; c o n s ti n t* p=& a ;/ / o b j e t oc o n s t a n t eyp u n t e r ov a r i a b l e * p=1 5 ;/ /E R R O R :e lv a l o ra p u n t a d op o rpe sc o n s t a n t e . p = & b ;/ / C o r r e c t o :pp a s aaa p u n t a rau nn u e v oo b j e t o .

Pero de esta forma no es muy til declararlo, pues el que hicimos constante fue el valor al que apunte p, es decir, mejor hubisemos hecho que el puntero fuese una constante. FORMA CORRECTA:

i n ta = 1 0 , b = 2 0 ; i n t*c o n s tp=& a ;/ / o b j e t ov a r i a b l eyp u n t e r oc o n s t a n t e * p=1 5 ;/ /C o r r e c t o :E lv a l o ra p u n t a d oe sv a r i a b l e . p = & b ;/ / E R R O R :pe sc o n s t a n t e .

Punteros Genericos
Un puntero a cualquier tipo de dato puede convertirse a un puntero del tipo void *. Por esto un puntero a void *, recibe el nombre de puntero generico. En C, se permite la conversin implcita de punteros, pero en C++ esto no es posible, asi que por compatibilidad y buena practica recomendamos usar la conversion explicita (cast).
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros 4/10

4/3/2014

Programacin en C/Punteros - Wikilibros

Supongamos:

i n t* p u n t e r o ; f u n c i o n( * p u n t e r o ) ; . . . . v o i df u n c i o n( v o i d* p ) i n t* q ; q = ( i n t* ) p ;/ / E nCs ep o d r i ah a c e rq=p ;

Es decir que un puntero a void se puede usar sin importar el tipo de dato, recuerden que uno no puede trabajar con punteros que referencia a un tipo de dato diferente, como lo es un puntero a char, con un puntero a int.

Punteros y Matrices
Anteriormente decamos que una matriz es una secuencia de espacios en memoria, que nos permitan alojar datos en cada uno y un puntero es una variable que guarda la direccin de memoria, tambin decamos como recorre las direcciones de memoria con los operadores ++ y --. Aqu veremos como puede usarse un puntero como si de una matriz se tratase, luego de que veas que es tcnicamente lo mismo, te preguntaras por que usar punteros, pero estos son muy necesarios y nicos que nos permiten realizar cosas que con un array normal, no se puede, como asignarle memoria dinmica, etc...

# i n c l u d e< s t d i o . h > i n tm a i n ( ) { i n ta r r a y [ 1 0 ] = { 0 , 2 , 3 , 5 , 5 , 6 , 7 , 8 , 9 , 0 } ;/ / D e c l a r a rei n i c i a l i z a ru na r r a y . i n t* p u n t e r o=& a r r a y [ 0 ] ;/ / L ed a m o sl ad i r e c c i nd ei n i c i od e la r r a y i n ti ;/ / v a r i a b l ec o n t a d o r a . . . f o r( i = 0 ; i < 1 0 ; i + + ) p r i n t f ( " % d \ n " , * ( p u n t e r o + i ) ) ;/ / i m p r i m i m o sl o sv a l o r e sd e lp u n t e r o . r e t u r n0 ; }

Habrs notado que he usado *(puntero+i), as como explica la seccin de operaciones aritmticas, pero tambin podemos acceder de otras maneras como lo son: array[i] => Accede como un array normal (array+i) => Tambin accede como un array normal. puntero[i] => Accedemos al valor de puntero sub i (puntero+i) => Accedemos al valor de puntero + 1
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros 5/10

4/3/2014

Programacin en C/Punteros - Wikilibros

Punteros a cadenas de caracteres


Ya hemos visto el uso que se le puede dar a un puntero como si de un array se tratase, entonces usando esta misma logica podemos hacer un array de caracteres usando punteros.

c h a r* n o m b r e = " G u s t a v oA .C h a v a r r i a " ; / / E sc o m ou na r r a yd e2 0c a r a c t e r e s p r i n t f ( " % s " , n o m b r e ) ;

Sin embargo al tratarse de una constante de caracteres no podemos modificarla luego de definir sus valores. Como por ejemplo no podemos remplazar un carcter, o leer un nuevo valor.

g e t s ( n o m b r e ) ;/ / E R R O Re ne j e c u c i n

Para poder modificar el valor de este puntero, este tendra que apuntar a una direccin que no sea una constante, como un array.

c h a rn o m b r e [ ] = " G u s t a v oA .C h a v a r r i a " ;/ / d e c l a r a m o su na r r a yd ec a r a c t e r e s c h a r* p u n t e r o = n o m b r e ; / / A s i g n a m o sa lp u n t e r oe lc o m i e n z od e la r r a y p r i n t f ( " % s\ n I n g r e s eo t r on o m b r e :" , p u n t e r o ) ; / / E s c r i b i m o se np a n t a l l an o m b r e . . . g e t s ( p u n t e r o ) ;/ / l e e m o so t r on o m b r e p r i n t f ( " % s " , p u n t e r o ) ;/ / e s c r i b i m o se ln u e v on o m b r e . . .

Esta vez pudiste notar que si se pudo remplazar el valor del nombre, pero aun la cantidad de caracteres esta limitada por el array original, mas adelante veremos como solucionar esto con memoria dinmica.

Matrices de Punteros
Es muy probable que ya te hayas dicho: Si un puntero es una variable, Puedo tener un array de punteros? La respuesta seria NO Exactamente. Como ya habiamos explicado antes, un puntero trabaja de la misma forma que un array, tanto que podemos decir que un puntero es un array, entonces si definimos un array de un array, nos dara como resultados un array bidimensional. En la practica es mucho mas comn utilizar un array de punteros que un array bidimensional. Hay que recordar que siguen siendo punteros, es decir solo apuntan a una direccin de memoria, por ende hay que asignarles la direccin de memoria a cada uno de los elementos del puntero. Sin embargo podemos asignar en un solo ciclo todas las filas. Ejemplo:

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros

6/10

4/3/2014

Programacin en C/Punteros - Wikilibros

# i n c l u d e< s t d i o . h > i n tm a i n ( ) { i n t* p u n t e r o [ 5 ] ;/ / a r r a yd ep u n t e r o i n ta [ 5 ] [ 5 ] ;/ / A r r a yb i d i m e n s i o n a l . i n ti ; f o r( i = 0 ; i < 5 ; i + + ) p u n t e r o [ i ] = a [ i ] ;/ / A s i g n a m o sl a sf i l a sa lp u n t e r o . / / P u e d e ni m p r i m i rt a m b i e ne nu nc i c l o / / T a m b i e np u e d e na c c e d e rm e d i a n t eu nc i c l oa n i d a d oal av a r i a b l e sd e lp u n t e r o [ i ] [ j ] }

Punteros a Punteros
Es una variable que contiene la direccin de memoria de un puntero, el cual a su vez contiene la direccin de memoria de un tipo de dato. Recuerden que un puntero sigue siendo un espacio en memoria, pero en vez de almacenar un valor almacena una direccin. Si decimos que:

i n ta = 0 ;/ / S u p o n g a m o sq u ee su n av a r i a b l ec u y ad i r e c c i o ne s0 x 1 6 0 1 i n t* p u n t e r o 1 = & a ;/ / E lp u n t e r ot i e n eg u a r d a d al ad i r e c c i o nd ea , / / p e r oe s t et i e n ec o m od i r e c c i o n0 x 1 8 9 0 i n t* * p u n t e r o 2 = & p u n t e r o 1 ;/ / * * p u n t e r o2g u a r d al ad i r e c c i o n0 x 1 8 9 0

Ahora se entiende mejor. Al uso de punteros se le llama variables con niveles de indireccion, ya que no apuntan directamente a un valor, sino que apuntan a alguien que lo tiene. Basndonos en esto podemos decir que *puntero1 es un puntero con un nivel de indireccion y *puntero2 es un puntero con dos niveles de indireccion. En general estos tipos de datos son usados con matrices multidimensionales, es por esto que decid no dejar ejemplos, pues su uso es bastante fcil de implementar.

Matrices de punteros a cadenas de caracteres


No hablaremos sobre este tema, debido a que es prcticamente una matriz de caracteres que se usa mediante punteros, y esto es tcnicamente lo mismo que hemos estado viendo anteriormente. Tambien podemos usar punteros a punteros y guardar multiples cadenas.

Ejemplos
Tenga en cuenta el siguiente bloque de cdigo que declara 2 punteros
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros 7/10

4/3/2014

Programacin en C/Punteros - Wikilibros

/ * 1 * /s t r u c tM y S t r u c t{ / * 2 * /i n tm _ a N u m b e r ; / * 3 * /f l o a tn u m 2 ; / * 4 * /} ; / * 5 * / / * 6 * /i n t*p J 2 ; / * 7 * /s t r u c tM y S t r u c t*p A n I t e m ;

Las primeras 4 lneas definen la estructura. La linea 6 declara una variable que apuntar a un entero, y la lnea 7 declara una variable que apunta a algo de la estructura MyStruct. Entonces declarar un puntero es algo que apunta a algo de algn tipo, ms que contener el tipo. El asterisco (* ) se coloca antes del nombre de la variable. En las siguientes lneas de cdigo, v a r 1es un puntero a un entero largo (l o n g ) mientras v a r 2es un entero largo (l o n g ) y no un puntero a un entero largo. En la segunda lnea se declara p 3como un puntero a un puntero de un entero.

l o n g*v a r 1 ,v a r 2 ; i n t* *p 3 ;

Los punteros se usan habitualmente como parmetros de funciones. El siguiente cdigo muestra como declarar una funcin que usa un puntero como argumento. Teniendo en cuenta que C pasa todos los argumentos por valor, para poder modificar un valor desde el cdigo de la funcin, se debe usar un puntero al valor a modificar. Tambin se usan punteros a estructuras como argumentos de una funcin an cuando la estructura no sea modificada dentro de la funcin. Esto es realizado para evitar copiar todo el contenido de la estructura dentro de la pila.

i n tM y F u n c t i o n (s t r u c tM y S t r u c t* p S t r u c t) ;

Asignando valores a punteros


Continuamos con el proceso de asignar valores a los punteros, para esto utilizamos el operador &o 'la direccin de'.

i n tm y I n t ; i n t* p P o i n t e r ; s t r u c tM y S t r u c td v o r a k ; s t r u c tM y S t r u c t* p K e y b o a r d ; p P o i n t e r=& m y I n t ; p K e y b o a r d=& d v o r a k ;

Aqu, pPointer apuntara a myInt y pKeyboard apuntara a dvorak.

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros

8/10

4/3/2014

Programacin en C/Punteros - Wikilibros

Los punteros tambin pueden ser asignados a referencias de memorias dinamicas creadas comnmente por las funciones malloc() y calloc().

# i n c l u d e< s t d l i b . h > . . . s t r u c tM y S t r u c t* p K e y b o a r d ; . . . p K e y b o a r d=m a l l o c ( s i z e o f ( s t r u c tM y S t r u c t ) ) ; . . .

La funcin malloc retorna un puntero de memoria asignada de manera dinmica (o NULL si falla). El tamao de esta memoria es definido de modo que pueda contener la estructura MyStruct El siguiente cdigo es un ejemplo mostrando un puntero siendo asignado a una referencia y se retorna el valor del puntero en la funcin.

s t a t i cs t r u c tM y S t r u c tv a l 1 ,v a l 2 ,v a l 3 ,v a l 4 ; . . . s t r u c tM y S t r u c t* A S i l l y F u n c t i o n (i n tb) { s t r u c tM y S t r u c t* m y R e t u r n ; i f( b= =1 )m y R e t u r n=& v a l 1 ; e l s ei f( b = = 2 )m y R e t u r n=& v a l 2 ; e l s ei f( b = = 3 )m y R e t u r n=& v a l 3 ; e l s em y R e t u r n=& v a l 4 ; } r e t u r nm y R e t u r n ; . . . s t r u c tM y S t r u c t* s t r P o i n t e r ; i n t* c ,* d ; i n tj ; . . . c=& j ;/ *p u n t e r oa s i g n a d ou s a n d oe lo p e r a d o r&* / d=c ;/ *a s i g n a n d ou np u n t e r oao t r o* / s t r P o i n t e r=A S i l l y F u n c t i o n (3) ;/ *p u n t e r or e t o r n a d od el af u n c i o n* /

Cuando se retorna un puntero de una funcion, se tiene que tener cuidado de que el valor apuntado no sea de una referencia de una variable local a la funcion, porque estos valores desaparecen despues de salir de la funcion y el puntero estaria mal referenciado, causando errores en tiempo de ejecucion en el programa. La memoria creada dinamicamente dentro de la funcion puede devolverse como puntero, el valor de retorno aunque es creado en una variable local la direccion como tal se devuelve por valor dejando esta informacion valida.

Estructuras y Uniones

Punteros

Manejo dinmico de memoria

Obtenido de http://es.wikibooks.org/w/index.php?title=Programacin_en_C/Punteros&oldid=219641 Categora: Programacin en C Esta pgina fue modificada por ltima vez el 9 feb 2014, a las 21:03. El texto est disponible bajo la Licencia Creative Commons Atribucin/Compartir-Igual 3.0; pueden
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros 9/10

4/3/2014

Programacin en C/Punteros - Wikilibros

aplicarse trminos adicionales. Vase Trminos de uso para ms detalles.

http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros

10/10