Está en la página 1de 15

Punteros

Definicin
Un puntero es un dato que contiene una direccin de memoria.


NOTA: Existe una direccin especial que se representa por medio de la
constante NULL (definida en <stdlib.h>) y se emplea cuando
queremos indicar que un puntero no apunta a ninguna direccin.


Declaracin

<t i po> *<i dent i f i cador >

<t i po>
Tipo de dato del objeto referenciado por el puntero

<i dent i f i cador >
Identificador de la variable de tipo puntero.


Cuando se declara un puntero se reserva memoria para albergar una direccin de
memoria, pero NO PARA ALMACENAR EL DATO AL QUE APUNTA EL PUNTERO.

El espacio de memoria reservado para almacenar un puntero es el mismo
independientemente del tipo de dato al que apunte: el espacio que ocupa una
direccin de memoria.


char c = a ;

char *pt r c;

i nt *pt r i ;


Operaciones bsicas con punteros


Direccin
Operador &

&<i d> devuelve la direccin de memoria donde comienza la variable <i d>.

El operador & se utiliza para asignar valores a datos de tipo puntero:


i nt i ;
i nt *pt r ;
. . .
pt r = &i ;



Indireccin
Operador *

*<pt r > devuelve el contenido del objeto referenciado por el puntero <pt r >.

El operador * se usa para acceder a los objetos a los que apunta un puntero:


char c;
char *pt r ;

pt r = &c;
*pt r = A ; / / Equi val e a escr i bi r : c = A
Asignacin
Operador =


A un puntero se le puede asignar una direccin de memoria concreta, la
direccin de una variable o el contenido de otro puntero.


Una direccin de memoria concreta:

i nt *pt r ;
. . .
pt r = 0x1F3CE00A;
. . .
pt r = NULL;


La direccin de una variable del tipo al que apunta el puntero:

char c;
char *pt r ;
. . .
pt r = &c;


Otro puntero del mismo tipo:

char c;
char *pt r 1;
char *pt r 2;

pt r 1 = &c;
pt r 2 = pt r 1;


Como todas las variables, los punteros tambin contienen basura cuando se
declaran, por lo que es una buena costumbre inicializarlos con NULL.

Ejemplo

i nt mai n ( )
{
i nt y = 5;
i nt z = 3;
i nt *npt r ;
i nt *mpt r ;


npt r = &y;




z = *npt r ;




*npt r = 7;



mpt r = npt r ;




mpt r = *z;



*mpt r = *npt r ;



y = ( *npt r ) + 1;

r et ur n 0;
}


Errores comunes

Asignar punteros de distinto tipo

i nt a = 10;
i nt *pt r i = NULL;
doubl e x = 5. 0;
doubl e *pt r f = NULL;
. . .
pt r i = &a;
pt r f = &x;
pt r f = pt r i ; / / ERROR


Utilizar punteros no inicializados

char *pt r ;

*pt r = a ; / / ERROR


Asignar valores a un puntero y no a la variable a la que apunta

i nt n;
i nt *pt r = &n;

pt r = 9; / / ERROR


Intentar asignarle un valor al dato apuntado por un puntero cuando ste es NULL

i nt *pt r = NULL;

*pt r = 9; / / ERROR



Punteros a punteros

Un puntero a puntero es
un puntero que contiene la direccin de memoria de otro puntero-


i nt mai n ( )
{
i nt a = 5;
i nt *p; / / Punt er o a ent er o
i nt **q; / / Punt er o a punt er o





p = &a;




q = &p;
}



Para acceder al valor de la variable a podemos escribir

a (forma habitual)

*p (a travs del puntero p)

**q (a travs del puntero a puntero q)

q contiene la direccin de p, que contiene la direccin de a

Aritmtica de punteros
Correspondencia entre punteros y vectores


Cuando declaramos un vector

<t i po> <i dent i f i cador > [ <di m>]

en realidad

1. Reservamos memoria para almacenar <di m> elementos de tipo <t i po>.

2. Creamos un puntero <i dent i f i cador > que apunta a la primera
posicin de la memoria reservada para almacenar los componentes del
vector.

Por tanto, el identificador del vector es un puntero.

i nt v[ 3] ;
i nt *pt r ;
. . .
pt r = v; / / Equi val e a pt r = &v[ 0]
v[ 0] = 6; / / *v = 6; *( &v[ 0] ) = 6;


Aritmtica de punteros

<t i po> *pt r ;

pt r + <despl azami ent o> devuelve un puntero a la posicin de memoria
si zeof ( <t i po>) *<despl azami ent o> bytes por encima de pt r .

i nt v[ ] ;
i nt *pt r = v; pt r +i apunta a v[ i ]

*( pt r +i ) v[ i ]


NOTA: La suma de punteros no tiene sentido y no est permitida. La resta slo
tiene sentido cuando ambos apuntan al mismo vector y nos da la distancia
entre las posiciones del vector (en nmero de elementos).
Ejemplo: Distintas formas de sumar los elementos de un vector

i nt suma ( i nt v[ ] , i nt N)
{
i nt i , suma;
i nt *pt r , *pt r f i n;

/ * Al t er nat i va 1 */
suma = 0;
f or ( i =0 ; i <N ; i ++)
suma = suma + v[ i ] ;

/ * Al t er nat i va 2 */
suma = 0;
f or ( i =0 ; i <N ; i ++)
suma = suma + ( *( v+i ) ) ;

/ * Al t er nat i va 3 */
suma = 0;
pt r f i n = pt r + N- 1;
f or ( pt r =v ; pt r <=pt r f i n ; pt r ++)
suma = suma + *pt r ;

r et ur n suma;
}

Punteros y matrices
<t i po> mat [ <di mF>] [ <di mC>] ;



direccin(i,j) =direccin(0,0) +i*dimC +j

Ejemplo: Intercambio de valores


voi d Cambi a( i nt *a, i nt *b)
{
i nt aux;

aux = *a;
*a = *b;
*b = aux;
}

i nt mai n( )
{
i nt x=0, y=1;

Cambi a( &x, &y) ;

r et ur n 0;
}





Gestin dinmica de la memoria

Organizacin de la memoria


Segmento de cdigo (cdigo del programa).

Memoria esttica (variables globales y estticas).

Pila (stack): Variables automticas (locales).

Heap (montn): Variables dinmicas.







Reserva y liberacin de memoria

Cuando se quiere utilizar el heap, primero hay que reservar la memoria que se
desea ocupar:
ANSI C: Funcin mal l oc
C++: Operador new

Al reservar memoria, puede que no quede espacio libre suficiente, por lo que
hemos de comprobar que no se haya producido un fallo de memoria (esto es, ver
si la direccin de memoria devuelta es distinta de NULL).

Tras utilizar la memoria reservada dinmicamente, hay que liberar el espacio
reservado:
ANSI C: Funcin f r ee
C++: Operadore del et e

Si se nos olvida liberar la memoria, ese espacio de memoria nunca lo podremos
volver a utilizar



Ejemplo: Vector de tamao dinmico

#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>

f l oat medi a ( f l oat v[ ] , i nt n)
{
i nt i ;
f l oat suma = 0;

f or ( i =0; i <n; i ++)
suma += v[ i ] ;

r et ur n suma/ n;
}


i nt mai n( i nt ar gc, char *ar gv[ ] )
{
i nt i ;
i nt n;
f l oat *v;

pr i nt f ( " Nmer o de el ement os del vect or : " ) ;
scanf("%d",&n);

/ / Cr eaci n del vect or

v = malloc(n*sizeof(float));

/ / Manej o del vect or

f or ( i =0; i <n; i ++)
v[ i ] = i ;

pr i nt f ( " Medi a = %f \ n" , medi a( v, n) ) ;

/ / Li ber aci n de memor i a

free(v);

r et ur n 0;
}

Ejemplo: TDA Vector Dinmico


Tipo de los elementos del vector dinmico

t ypedef i nt Dat o;

Estructura de datos del vector

t ypedef st r uct Vect or {
Dat o *dat os; / / Vect or de dat os
i nt usado; / / El ement os usados del vect or
i nt capaci dad; / / Capaci dad del vect or
};

t ypedef st r uct Vect or *Vect or ;


Creacin del vector (constructor)

Vect or cr ear Vect or ( voi d)
{
Vect or v =( Vect or ) mal l oc ( si zeof ( st r uct Vect or ) ) ;

v- >usado = 0;
v- >capaci dad = 2;
v- >dat os = mal l oc ( ( v- >capaci dad) *si zeof ( Dat o) ) ;

r et ur n vect or ;
}

Destruccin del vector (destructor)

voi d dest r ui r Vect or ( Vect or *v)
{
f r ee ( ( *v) - >dat os ) ;
f r ee ( *v ) ;

*v = NULL;
}
Constructor y destructor nos permiten manejar vectores sin
tener que conocer su estructura de datos interna (ni siquiera
tendremos que utilizar mal l oc y f r ee).
Acceso al contenido del vector
Funciones que permiten ocultar los detalles de implementacin del TDA


Nmero de elementos del vector:


i nt el ement osVect or ( Vect or v)
{
r et ur n v- >usado;
}


Acceso a los elementos concretos del vector:


Obtencin del valor almacenado en una posicin del vector:


Dat o obt ener Dat o ( Vect or v, i nt pos)
{
i f ( ( pos>=0) && ( pos<el ement osVect or ( v) ) )
r et ur n v- >dat os[ pos] ;
el se
r et ur n NULL;
}


Modificacin del valor almacenado en una posicin del vector:


voi d guar dar Dat o ( Vect or v, i nt pos, Dat o dat o)
{
i f ( ( pos>=0) && ( pos<el ement osVect or ( v) ) ) {
v- >dat os[ pos] = dat o;
}
}

Insercin de datos

voi d agr egar Dat o ( Vect or v, Dat o dat o)
{
i nt i ;
Dat o *dat os;

i f ( v- >usado == v- >capaci dad) {

/ / Redi mensi onar el vect or
v- >capaci dad *= 2;
dat os = mal l oc ( ( v- >capaci dad) *si zeof ( Dat o) ) ;

f or ( i =0; i < v- >usado; i ++)
dat os[ i ] = v- >dat os[ i ] ;

f r ee( v- >dat os) ;
v- >dat os = dat os;
}

v- >dat os[ v- >usado] = dat o;
v- >usado ++;
}

Eliminacin de datos

voi d el i mi nar Dat o ( Vect or v, i nt pos)
{
i nt i ;

i f ( ( pos>=0) && ( pos<el ement osVect or ( v) ) ) {

f or ( i =pos; i <el ement osVect or ( v) - 1; i ++)
v- >dat os[ i ] = v- >dat os[ i +1] ;

v- >usado - - ;
}
}


OJ O! En la implementacin mostrada no contemplamos la
posibilidad de que la funcin malloc devuelva NULL
(algo que siempre deberemos hacer al programar).
Ejemplo de uso del TDA Vector Dinmico


#i ncl ude <st di o. h>
#i ncl ude vect or . h

/ * Rut i na auxi l i ar */

voi d most r ar Vect or ( Vect or v)
{
i nt i ;

pr i nt f ( " Vect or de t amao %d: \ n" ,
el ement osVect or ( v) ) ;

f or ( i =0; i <el ement osVect or ( v) ; i ++)
pr i nt f ( " - %d\ n" , obt ener Dat o( v, i ) ) ;
}


/ * Pr ogr ama pr i nci pal */

i nt mai n ( )
{
Vect or v = cr ear Vect or ( ) ;

most r ar Vect or ( v) ;

agr egar Dat o ( v, 1) ;
agr egar Dat o ( v, 2) ;
agr egar Dat o ( v, 3) ;
most r ar Vect or ( v) ;

el i mi nar Dat o ( v, 1) ;
most r ar Vect or ( v) ;

guar dar Dat o ( v, 0, obt ener Dat o( v, 0) +2) ;
most r ar Vect or ( v) ;

dest r ui r Vect or ( &v) ;

r et ur n 0;
}

También podría gustarte