Documentos de Académico
Documentos de Profesional
Documentos de Cultura
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;
}