Vous êtes sur la page 1sur 13

Apuntadores

Apuntadores

2013
TransversaldeProgramacinBsica
ProyectoCurriculardeIngenieradeSistemas

Apuntadores

Objetivos
1. Aprenderareferenciarvariables
2. Aprenderadeclararyasignarapuntadores
3. Identificarlasrazonesporlascualesunapuntadorpuedepasaracontenerunadireccin
invalida.
4. Aprenderaasignarmemoriadinmicamente

Introduccin
LosapuntadoresenCyC++sonunaherramientamuypotentedeprogramacinquesuelecausar
mucha confusin en los estudiantes que la estn aprendiendo. Adems, cuando los
programadorescometenunerrorensuutilizacin,puedesermuydifcilencontrarelerror,porlo
cualesimportantesaberutilizarlosmuybien.ElusodeapuntadoresenCyC++esmuyimportante
debidoaquepermitehacerlosprogramasmseficientesymsflexibles.Enestedocumentose
explicadeunamanerasencillaybrevetodoloreferentealautilizacindeapuntadorestantoenC
comoenC++.

Definiciones

Definicindeapuntador

Cuandosedeclaraunavariable,elcompiladorreservaunespaciodememoriaparaellayasociael
nombredeestaaladireccindememoriadesdedondecomienzanlosdatosdeesavariable.Las
direccionesdememoriasesuelendescribircomonmerosenhexadecimal.

Unapuntadoresunavariablecuyovaloresladireccindememoriadeotravariable.Sediceque
unapuntadorapuntaalavariablecuyovalorsealmacenaapartirdeladireccindememoria
quecontieneelapuntador.Porejemplo,siunapuntadorpalmacenaladireccindeunavariable
x,sedicequepapuntaax.

Referenciacin

Lareferenciacineslaobtencindeladireccindeunavariable.EnCyC++estosehaceatravs
deloperador&,aplicadoalavariablealacualsedeseasabersudireccin.Ntesequesetrata
deunoperadorunario.Ejemplo:

intx=25;
cout<<"Ladireccindexes:"<<&x<<endl;

Apuntadores

Declaracindeapuntadores

Paradeclararunapuntadorseespecificaeltipodedatoalqueapunta,eloperador*,yel
nombredelapuntador.Lasintaxiseslasiguiente:

<tipodedatoapuntado>*<identificadordelapuntador>

Acontinuacinsemuestranvariosejemplos:

int*ptr1;//Apuntadoraundatodetipoentero(int)
char*cad1,*cad2;//Dosapuntadoresadatosdetipocaracter(char)
float*ptr2;//Apuntadoraundatodetipopuntoflotante(float)

Asignacindeapuntadores

Sepuedenasignaraunapuntadordireccionesdevariablesatravsdeloperadordereferenciacin
(&)odireccionesalmacenadasenotrosapuntadores.Ejemplos:

inti=5;
int*p,*q;
p=&i;//Seleasignaapladireccindei
q=p;//Seleasignaaqladireccinalmacenadaenp(lamismadei)

Desreferenciacindeapuntadores

La desreferenciacin es la obtencin del valor almacenado en el espacio de memoria donde


apuntaunapuntador.EnCyC++estosehaceatravsdeloperador*,aplicadoalapuntadorque
contieneladireccindelvalor.Ntesequesetratadeunoperadorunario.Ejemplos:

intx=17,y;
int*p;
p=&x;
cout<<"Elvalordexes:"<<*p<<endl;//Imprime17
y=*p+3;//Ayseleasigna20

C++ademsproveeeloperadorbinario>,utilizadoparaobtenercamposdeunregistroconun
apuntador al mismo de una manera ms fcil y legible. Muchos compiladores de C tambin
soportanesteoperador.

Apuntadores

Ejemplo

structData
{
charnombre[20];
intedad;
};
Datad;
Data*pd=&d;
(*pd).edad=23;//Accesoalcampoedadutilizandoeloperador.
pd>edad=23;//Accesoalcampoedadutilizandoeloperador>
cout<<(*pd).edad<<endl;
cout<<pd>edad<<endl;

Verificacindetiposenapuntadores

Al igual que el resto de las variables, los apuntadores se enlazan a tipos de datos especficos
(apuntadoresavariablesdeciertotipo),demaneraqueaunapuntadorsoloselepuedenasignar
direccionesdevariablesdeltipoespecificadoenladeclaracindelapuntador.

Ejemplo

int*p1;
float*p2;
intx;
p1=&x;//Estoesvalido
p2=&x;//Estonoesvalido(elcompiladorgeneraunerror)

DireccionesinvalidasyladireccinNULL

Normalmente,unapuntadorinicializadoadecuadamenteapuntaaalgunaposicinespecficadela
memoria. Sin embargo, algunas veces es posible que un apuntador no contenga una direccin
vlida, en cuyo caso es incorrecto desreferenciarlo (obtener el valor al que apunta) porque el
programatendruncomportamientoimpredecibleyprobablementeerrneo,aunqueesposible
quefuncionebien.

Unapuntadorpuedecontenerunadireccininvlidadebidoadosrazones:

1. Cuandounapuntadorsedeclara,aligualquecualquierotravariable,elmismoposeeun
valorcualquieraquenosepuedeconocerconantelacin,hastaqueseinicialiceconalgn
valor(direccin).

Apuntadores

Ejemplo

float*p;
cout<<"Elvalorapuntadoporpes:"<<*p<<endl;//Incorrecto
*p=3.5;//Incorrecto

2. Despusdequeunapuntadorhasidoinicializado,ladireccinqueposeepuededejarde
ser vlida si se libera la memoria reservada en esa direccin, ya sea porque la variable
asociada termina su mbito o porque ese espacio de memoria fue reservado
dinmicamenteyluegoselibero.

Ejemplo

int*p,y;
voidfunc()
{
intx=40;
p=&x;
y=*p;//Correcto
cout<<"funcy="<<y<<endl;
*p=23;//Correcto
cout<<"func*p="<<*p<<endl;
}

intmain(intargc,char*argv[])
{

func();
cout<<"y="<<y<<endl;
cout<<"*p="<<*p<<endl;
y=*p;//Incorrecto
cout<<"y="<<y<<endl;
*p=25;//Incorrecto
cout<<"*p="<<*p<<endl;

Apuntadores

Si se intenta desreferenciar un apuntador que contiene una direccin invlida pueden ocurrir
cosascomolassiguientes:

Seobtieneunvalorincorrectoenunaomsvariablesdebidoaquenofuedebidamente
inicializada la zona de memoria que se accede a travs de la direccin en cuestin. Esto
puedeocasionarqueelprogramagenereresultadosincorrectos.

Sicasualmenteladireccineslamismadeotravariableutilizadaenelprograma,oest
dentro del rango de direcciones de una zona de memoria utilizada, existe el riesgo de
sobrescribirdatosdeotrasvariables.

Existe la posibilidad de que la direccin est fuera de la zona de memoria utilizada para
almacenar datos y ms bien est, por ejemplo, en la zona donde se almacenan las
instrucciones del programa. Al intentar escribir en dicha zona, fcilmente puede ocurrir
queelprogramagenereunerrordeejecucinyelsistemaoperativolodetenga,oqueel
programanorespondaydejealsistemaoperativoinestable.

En muchos casos el sistema operativo detecta el acceso inadecuado a una direccin de


memoria,encuyocasodetieneabruptamenteelprograma.

Cuandonosedeseaqueunapuntadorapunteaalgo,selesueleasignarelvalorNULL,encuyo
casosedicequeelapuntadoresnulo(noapuntaanada).NULLesunamacrotpicamentedefinida
enarchivosdecabeceracomostdef.hystdlib.h.Normalmente,enC++seencuentradisponiblesin
incluirningnarchivodecabecera.NULLsesueledefinirenestaslibrerasas:

#defineNULL0

Unapuntadornuloseutilizaparaproporcionaraunprogramaunmediode conocercundoun
apuntador contiene una direccin vlida. Se suele utilizar un test condicional para saber si un
apuntadoresnuloonoloes,ytomarlasmedidasnecesarias.

ElvalorNULLesmuytilparalaconstruccindeestructurasdedatosdinmicas,comolaslistas
enlazadas,matricesesparcidas,etc.EsigualmenteincorrectodesreferenciarelvalorNULLporlas
mismasrazonespresentadaspreviamente.

Apuntadoresaapuntadores

Dadoqueunapuntadoresunavariablequeapuntaaotra,fcilmentesepuedededucirque
puedenexistirapuntadoresaapuntadoresyasuvezlossegundospuedenapuntaraapuntadores,
yassucesivamente.

Estosapuntadoressedeclarancolocandotantosasteriscos(*)comoseanecesario.

Apuntadores

Ejemplo

charc='z';
cout<<"c:"<<c<<endl;
char*pc=&c;
char**ppc=&pc;
char***pppc=&ppc;
***pppc='m';//Cambiaelvalordecam
cout<<"c:"<<c<<endl;
cout<<"&c:"<<&c<<endl;
cout<<"*pc"<<*pc<<endl;
cout<<"&pc"<<&pc<<endl;
cout<<"**ppc"<<**ppc<<endl;
cout<<"&ppc"<<&ppc<<endl;
cout<<"***pppc"<<***pppc<<endl;
cout<<"&pppc"<<&pppc<<endl;

Apuntadoresconstantesyapuntadoresaconstantes

Esposibledeclararapuntadoresconstantes.Deestamanera,nosepermitelamodificacindela
direccinalmacenadaenelapuntador,perossepermitelamodificacindelvaloralqueapunta.
Ejemplo:

intx=5,y=7;
int*constp=&x;//Declaracineinicializacindelapuntador
constante
*p=3;//Estoesvlido
p=&y;//Estonoesvlido(elcompiladorgeneraunerror)

Tambin es posible declarar apuntadores a datos constantes. Esto hace que no sea posible
modificarelvaloralqueapuntaelapuntador.Ejemplo:

Apuntadores

intx=5,y=7;
constint*p=&x;//Declaracineinicializacindelapuntadoraconstante
p=&y;//Estoesvlido
*p=3;//Estonoesvlido(elcompiladorgeneraunerror)
y=3;//Estoesvlido

Apuntadores,arreglosyaritmticadeapuntadores

Losarreglosyapuntadoresestnfuertementerelacionados.Elnombredeunarregloes
simplementeunapuntadorconstantealiniciodelarreglo.Sepuedendireccionararregloscomosi
fueranapuntadoresyapuntadorescomosifueranarreglos.

Ejemplos

intlista_arr[5]={10,20,30,40,50};
int*lista_ptr;
lista_ptr=lista_arr;//Apartirdeaquambasvariablesapuntanalmismositio
cout<<lista_arr[0]<<endl;//Imprime10
cout<<lista_ptr[0]<<endl;//Instruccinequivalentealaanterior
cout<<*lista_arr<<endl;//Instruccinequivalentealaanterior
cout<<*lista_ptr<<endl;//Instruccinequivalentealaanterior
cout<<lista_arr[3]<<endl;//Imprime40
cout<<lista_ptr[3]<<endl;//Instruccinequivalentealaanterior

Esposiblesumaryrestarvaloresenterosaunapuntador.Elresultadodeestasoperacionesesel
desplazamientodeladireccindememoriahaciaadelante(suma)ohaciaatrs(resta)por
bloquesdebytesdeltamaodeltipodedatoapuntadoporelapuntador.Estopermiterecorrer
arreglosutilizandoapuntadores.

Ejemplos

intlista[5]={10,20,30,40,50};
int*p;
charcad[15];
char*q;
p=&lista[3];//palmacenaladirecciondelaposicion3delarreglo
p=lista+3;//Instruccionequivalentealaanterior
cout<<lista[2]<<endl;//Imprime30;
cout<<*(lista+2)<<endl;//Instruccionequivalentealaanterior
//Lassiguientesinstruccionesimprimenlapalabra"Programando"
/*Nota:Recuerdesequeunaconstantedecadenadecaractereses
unasecuenciadecaracteresenmemoriaseguidosdelcaracternulo*/
strcpy(cad,"Programando");
for(q=cad;*q!='\0';q++)

Apuntadores

cout<<*q;
cout<<endl;

Tambin es posible restar dos apuntadores. El resultado de esta operacin es el nmero de


bloquesdebytesquehayentrelasdosdireccionesdeltamaodeltipodedatoapuntadoporlos
apuntadores.

doublex[5]={1.1,2.1,3.1,4.1,
5.1};
double*p=&x[1],
*q=&x[4];
cout<<"*p:"<<*p<<endl;
cout<<"*q:"<<*q<<endl;
cout<<"p:"<<p<<endl;
cout<<"q:"<<q<<endl;
intn;
n=qp;//anseleasigna3
cout<<"n:"<<n<<endl;
n=q++p;//anseleasigna3
cout<<"n:"<<n<<endl;

Apuntadoresparapasodeparmetrosporreferencia

EllenguajeCnoproveeunamaneradepasarparmetrosporreferencia.Sinembargo,esposible
hacerlo atreves del uso de apuntadores. A continuacin se muestra un ejemplo del paso de un
parmetro por referencia en C++, y luego un cdigo equivalente en C o C++ utilizando un
apuntador:

voidsuma(inta,intb,int&r)
{
r=a+b;
}

intmain(intargc,char*argv[])
{
intx;
suma(7,5,x);
cout<<"7+5="<<x;
system("PAUSE");
returnEXIT_SUCCESS;
}

Apuntadores

Otroejemplodeapuntadores

voidsuma(inta,intb,int*r)
{
*r=a+b;
}

intmain(intargc,char*argv[])
{
intx;
suma(7,5,&x);
cout<<"7+5="<<x;

system("PAUSE");
returnEXIT_SUCCESS;

Ntese que en ambos casos se utiliza el operador & para cosas distintas. El operador & tiene
dos significados como operador unario: sealizacin de parmetro por referencia y operador de
referenciacin.

Asignacindinmicadememoria

Losprogramaspuedencrearvariablesglobalesolocales.Lasvariablesdeclaradasglobalesensus
programassealmacenanenposicionesfijasdememoria,enlazonaconocidacomosegmentode
datosdelprograma,ytodaslasfuncionespuedenutilizarestasvariables.Lasvariableslocalesse
almacenan en la pila (stack) y existen slo mientras estn activas las funciones donde estn
declaradas. En ambos casos el espacio de almacenamiento se reserva en el momento de la
compilacindelprograma.

Tambin es posible reservar y utilizar memoria dinmicamente, tomada de la zona de memoria


llamadamontculo(heap) oalmacnlibre.EnCestndisponiblesvariasfuncionesquepermiten
realizar reservar y liberar memoria, pero C++ adems provee un mtodo ms fcil y seguro de
hacerlo.

ParaasignarmemoriadinmicamenteenC++seutilizanlosoperadoresnewydelete.Eloperador
newreservamemoriaparauntipodedatosespecificoyretornasudireccin,oretornaNULLen
casodenohaberconseguidosuficientememoria;yeloperadordeletepermiteliberarlamemoria
reservadaatravsdeunapuntador.Lasintaxisdeambosoperadoresescomosigue:

Parareservaryliberarunsolobloque:

<apuntador>=new<tipodedato>
delete<apuntador>

10

Apuntadores

Parareservaryliberarvariosbloques(unarreglo):

<apuntador>=new<tipodedato>[<nmerodebloques>]
delete[]<apuntador>

Eltipodelapuntadorespecificadodelladoizquierdodeloperadornewdebecoincidirconeltipo
especificadodelladoderecho.Denoseras,seproduceunerrordecompilacin.

Ejemplo

intmain(intargc,char*argv[])
{
structData
{
charnombre[20];
intedad;
};
Data*p_data;//DeclaraciondeunapuntadoraData
inti;
p_data=newData;//Reservaciondememoriaparaunregistro
if(p_data!=NULL)//Verificaciondereservacion
{
strcpy(p_data>nombre,"Rachel");//Inicializaciondedatos
p_data>edad=21;//enlamemoriareservada
cout<<p_data>nombre<<""<<(*p_data).edad<<endl;
deletep_data;//Liberaciondememoria
}
//Reservaciondememoriaparaunarreglode10registros
p_data=newData[10];
if(p_data!=NULL)//Verificaciondereservacion
{
//Lecturadedatosdelarreglo
for(i=0;i<10;i++){
cout<<"ingreseelnombreyedaddelelemto"<<i<<endl;
cin>>p_data[i].nombre>>p_data[i].edad;
}
for(i=0;i<10;i++)
cout<<"nombre"<<p_data[i].nombre<<"edad"<<p_data[i].edad<<"delelemto
"<<i<<endl;
//Liberaciondememoriadelarreglo
delete[]p_data;

11

Apuntadores

}
system("PAUSE");
returnEXIT_SUCCESS;
}

Problemas

1. Supongamosqueaybsonvariablesdetipoentero,Culserelvalorfinaldebdespusde
ejecutarlassiguientesinstrucciones?

a=a*a;
b=*(&a);

2. Lasiguientedeclaracinesvalida:

int**app;

Dequetipoeslavariableapp?Comopuedeasignarseunvaloraestavariable?Cmo
puedereferenciarsememoriaconella?

3. HagalafuncinHallarMaximo,querecibeunvectordeenterosyeltamaodetalvector.
Retornalaposicindelmximoyelmximoelementodelvector.(Ayuda:Puederetornaruno
oambosvaloresenparmetrospasadosporreferencia)

4. Escribirelprogramaqueordenalaslneasdeuntextoledodesdelaentradaestndar,donde
cadalneatienediferentelongitud

5. Escribirunafuncinqueconviertaunacadenasaunnmerodepuntoflotanteusando
apuntadores.Considerarqueelnmerotieneelsiguienteformato99999999.999999,esdecir,
nosedarennotacincientfica.Lafuncindebersuministrrseleunacadenaydeber
devolverunnmero.

Referencias
ProgramacinenC++,LuisJoyanesAguilar,editorialMcGrawHill.
http://www.programatium.com/manuales/c/9.htm#SECTION00990000000000000000

12

Apuntadores

LecturadeProfundizacin:

Textotomadode
http://www.itescam.edu.mx/principal/sylabus/fpdb/recursos/r43599.PDF

Imgenes
Lasimgenesfuerontomadasdewww.google.com
Fuentes:

http://prezi.com/pmiyyq6lkxo_/apuntadoresc/
http://estructuradedatosceutecfarias.blogspot.com/2010/04/apuntadoresenc.html
http://imv.com.ve/_descargas/2010
07/a5d55cbed49c6b29ae63b86ca5d4a5f9462943178manualsobreellenguajec.pdf
http://foro.elhacker.net/programacion_cc/c_listas_enlazadast341859.0.html

13

Vous aimerez peut-être aussi