Académique Documents
Professionnel Documents
Culture Documents
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
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.
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;
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.
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