fundamentos de la programación 2013 2014 9 · al copiarle otro puntero (con el mismo tipo base)...
TRANSCRIPT
13/05/2014
1
9
GradoenIngenieríaInformáticaGradoenIngenieríadelSoftware
GradoenIngenieríadeComputadores
LuisHernándezYáñez
FacultaddeInformáticaUniversidadComplutense
Fundamentos de la programación 2013‐2014
Luis Hernández Yáñez
Página 1Fundamentos de la programación: Punteros y memoria dinámica
Direcciones de memoria y punteros 2Operadores de punteros 7Punteros y direcciones válidas 17
Punteros no inicializados 19Un valor seguro: NULL 20
Copia y comparación de punteros 21Tipos de punteros 26
Punteros a estructuras 28Punteros a constantes y punteros constantes 30
Punteros y paso de parámetros 32Punteros y arrays 36Memoria y datos del programa 39Memoria dinámica 44Punteros y datos dinámicos 48Gestión de la memoria 61
Inicialización de datos dinámicos 64Errores comunes 66Arrays de datos dinámicos 71Arrays dinámicos 83
13/05/2014
2
Luis Hernández Yáñez
Página 2Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
LosdatosenlamemoriaTododato(variableoconstante)deunprogramasealmacenaenlamemoria:enunoscuantosbytesapartirdeunadirección.
int i = 5;
Eldato(i)seaccedeapartirdesudirecciónbase (0F03:1A38),ladireccióndelaprimeraceldadememoriautilizadaporesedato.Eltipodeldato(int)indicacuántasceldas(bytes)utilizaesedato(4):00000000 00000000 00000000 00000101 5(Lacodificacióndelosdatospuedeserdiferente.Yladelasdireccionestambién.)
Página 3Fundamentos de la programación: Punteros y memoria dinámica
0F03:1A37 ...
i 0F03:1A38 00000000
0F03:1A39 00000000
0F03:1A3A 00000000
0F03:1A3B 00000101
0F03:1A3C ...
5DirecciónbaseDirecciónbase
13/05/2014
3
Luis Hernández Yáñez
LospunteroscontienendireccionesdememoriaUnavariablepuntero (osimplementepuntero)sirveparaaccederatravésdeellaaotrodatodelprograma.
Elvalordelpunteroseráladireccióndememoriabasedeotrodato.
Página 4Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38 00
0F03:1A39 00
0F03:1A3A 00
0F03:1A3B 05
...
punt 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
...
¿Dequétipoeseldatoapuntado?¿Cuántasceldasocupa?¿Cómoseinterpretanlos0sy1s?
¿Dequétipoeseldatoapuntado?¿Cuántasceldasocupa?¿Cómoseinterpretanlos0sy1s?
Indirección:AccesoindirectoaundatoIndirección:Accesoindirectoaundato
puntpunt
5ii
punt apunta aipunt apunta ai
Luis Hernández Yáñez
Lospunteroscontienendireccionesdememoria¿Dequétipoeseldatoapuntado?
Lavariablealaqueapuntaunpuntero,comocualquierotravariable,serádeuntipoconcreto(¿cuántoocupa?¿cómoseinterpreta?).
Eltipodevariablealaqueapuntaunpunteroseestablecealdeclararlavariablepuntero:
tipo *nombre;
Elpunteronombre apuntaráaunavariabledeltipo indicado(eltipobasedelpuntero).
Elasterisco(*)indicaqueesunpunteroadatosdeesetipo.int *punt; // punt inicialmente contiene una dirección
// que no es válida (no apunta a nada).
Elpunteropunt apuntaráaunavariableentera(int).int i; // Dato entero vs. int *punt; // Puntero a entero
Página 5Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
4
Luis Hernández Yáñez
LospunteroscontienendireccionesdememoriaLasvariablespunterotampocoseinicializanautomáticamente.Aldeclararlassininicializadorcontienendireccionesquenosonválidas.int *punt; // punt inicialmente contiene una dirección
// que no es válida (no apunta a nada).
Unpunteropuedeapuntaracualquierdatodeltipobase.
Unpunteronotieneporquéapuntarnecesariamenteaundato(puedenoapuntaranada:valorNULL).
¿Paraquésirvenlospunteros?
Paraimplementarelpasodeparámetrosporreferencia.
Paramanejardatosdinámicos.(Datosquesecreanydestruyendurantelaejecución.)
Página 6Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Página 7Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
5
Luis Hernández Yáñez
Obtenerladireccióndememoriade...Eloperadormonario& devuelveladireccióndememoriabasedeldatoalqueseaplicaeloperador.Operadorprefijo(precede).int i;
cout << &i; // Muestra la dirección de memoria de i
Aunpunteroselepuedeasignarladirecciónbasedecualquierdatodelmismotipoqueeltipobasedelpuntero:int i;
int *punt;
punt = &i; // punt contiene la dirección base de i
Ahora,elpunteropunt yacontieneunadireccióndememoriaválida.
punt apunta a(contieneladirecciónbasede)lavariableenterai (int).
Página 8Fundamentos de la programación: Punteros y memoria dinámica
&&
puntpunt
5ii
Luis Hernández Yáñez
Obtenerladireccióndememoriade...
int i, j;
...
int *punt;
Página 9Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
&&
13/05/2014
6
Luis Hernández Yáñez
Obtenerladireccióndememoriade...
int i, j;
...
int *punt;
...
i = 5;
Página 10Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38 00
0F03:1A39 00
0F03:1A3A 00
0F03:1A3B 05
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
&&
5ii
Luis Hernández Yáñez
Obtenerladireccióndememoriade...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
Página 11Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38 00
0F03:1A39 00
0F03:1A3A 00
0F03:1A3B 05
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
...
&&
puntpunt
5ii
13/05/2014
7
Luis Hernández Yáñez
Obtenerloquehayenladirección...Eloperadormonario* accedealoquehayenladireccióndememoriaalaqueseaplicaeloperador(unpuntero).Operadorprefijo(precede).
Unavezqueunpunterocontieneunadireccióndememoriaválida,sepuedeaccederaldatoalqueapuntaconesteoperador.punt = &i;
cout << *punt; // Muestra lo que hay en la dirección punt
*punt:loquehayenladirecciónquecontieneelpunteropunt.
Comoelpunteropunt contieneladireccióndememoriadelavariablei,*punt accedealcontenidodeesavariablei.
Accesoindirectoalvalordei.
Seobtienen,apartirdeladireccióndememoriabasequecontienepunt,tantosbytescomocorrespondanaltipobase(int)(4)yseinterpretancomoundatodeesetipobase(int).
Página 12Fundamentos de la programación: Punteros y memoria dinámica
**Luis Hernández Yáñez
Obtenerladireccióndememoriade...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
j = *punt;
Página 13Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38 00
0F03:1A39 00
0F03:1A3A 00
0F03:1A3B 05
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
...
0F0F
0303
1A1A
3838punt:punt:
**
13/05/2014
8
Luis Hernández Yáñez
Obtenerladireccióndememoriade...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
j = *punt;
Página 14Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38 00
0F03:1A39 00
0F03:1A3A 00
0F03:1A3B 05
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
...
0000
0000
0000
0505
*punt:*punt:
**
Direccionamientoindirecto
(indirección). Se accede al dato ide forma indirecta.
Direccionamientoindirecto
(indirección). Se accede al dato ide forma indirecta.
Luis Hernández Yáñez
Obtenerladireccióndememoriade...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
j = *punt;
Página 15Fundamentos de la programación: Punteros y memoria dinámica
...
i 0F03:1A38 00
0F03:1A39 00
0F03:1A3A 00
0F03:1A3B 05
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
...
0000
0000
0000
0505
**
13/05/2014
9
Luis Hernández Yáñez
Ejemplodeusodepunteros#include <iostream>using namespace std;
int main() {int i = 5;int j = 13;int *punt;punt = &i;cout << *punt << endl; // Muestra el valor de ipunt = &j;cout << *punt << endl; // Ahora muestra el valor de jint *otro = &i;cout << *otro + *punt << endl; // i + jint k = *punt;cout << k << endl; // Mismo valor que j
return 0;}
Página 16Fundamentos de la programación: Punteros y memoria dinámica
punteros.cpp
Luis Hernández Yáñez
Página 17Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
10
Luis Hernández Yáñez
TodopunterohadetenerunadirecciónválidaUnpunterosólodebeserutilizadoparaaccederaldatoalqueapunte,siseestásegurodequecontieneunadirecciónválida.
UnpunteroNOcontieneunadirecciónválidatrasserdefinido.
Unpunteroobtieneunadirecciónválida:
Alcopiarleotropuntero(conelmismotipobase)queyacontengaunadirecciónválida.
Alasignarleladireccióndeotrodatoconeloperador&.
AlasignarleelvalorNULL (indicaquesetratadeunpunteronulo,unpunteroquenoapuntaanada).
int i;int *q; // q no tiene aún una dirección válidaint *p = &i; // p toma una dirección válidaq = NULL; // ahora q ya tiene una dirección válidaq = p; // otra dirección válida para q
Página 18Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Punterosqueapuntanasaberqué...Unapunteronoinicializadocontieneunadireccióndesconocida.int *punt; // no inicializado*punt = 12;
¿Direccióndelazonadedatosdelprograma?¡Podemosestarmodificandoinadvertidamenteundatodelprograma! Elprogramanoobtendríalosresultadosesperados.
¿Direccióndelazonadecódigodelprograma?¡Podemosestarmodificandoelpropiocódigodelprograma! Sepodríaejecutarunainstrucciónincorrecta ???
¿Direccióndelazonadecódigodelsistemaoperativo?¡PodemosestarmodificandoelcódigodelpropioS.O.! Consecuenciasimprevisibles(cuelgue)
Página 19Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
11
Luis Hernández Yáñez
PunterosquenoapuntananadaInicializandolospunterosaNULL podemosdetectarerrores:int *punt = NULL;...*punt = 13;
punt hasidoinicializadoaNULL:¡Noapuntaanada!
Sinoapuntaanada,¿¿¿quésignifica*punt???Notienesentido.
ERROR:¡Seintentaaccederaundatoatravésdeunpunteronulo!
Seproduceunerrordeejecución,loqueciertamentenoesbueno.
Perosabemosexactamentecuálhasidoelproblema,loqueesmucho.
Sabemospordóndeempezarainvestigar(depurar)yquébuscar.
Página 20Fundamentos de la programación: Punteros y memoria dinámica
Xpuntpunt
Luis Hernández Yáñez
Página 21Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
12
Luis Hernández Yáñez
ApuntandoalmismodatoCuandocopiamosunpunterosobreotro,ambosapuntanalmismodato:
int x = 5;int *punt1 = NULL; // punt1 no apunta a nadaint *punt2 = &x; // punt2 apunta a la variable x
Página 22Fundamentos de la programación: Punteros y memoria dinámica
Xpunt1punt1 punt2punt2
5xx
Luis Hernández Yáñez
ApuntandoalmismodatoCuandocopiamosunpunterosobreotro,ambosapuntanalmismodato:
int x = 5;int *punt1 = NULL; // punt1 no apunta a nadaint *punt2 = &x; // punt2 apunta a la variable xpunt1 = punt2; // ambos apuntan a la variable x
Página 23Fundamentos de la programación: Punteros y memoria dinámica
punt1punt1 punt2punt2
5xx
13/05/2014
13
Luis Hernández Yáñez
ApuntandoalmismodatoCuandocopiamosunpunterosobreotro,ambosapuntanalmismodato:
int x = 5;int *punt1 = NULL; // punt1 no apunta a nadaint *punt2 = &x; // punt2 apunta a la variable xpunt1 = punt2; // ambos apuntan a la variable x*punt1 = 8;
Página 24Fundamentos de la programación: Punteros y memoria dinámica
punt1punt1 punt2punt2
8xx
Alavariablexahorasepuedeaccederde3formas:
x *punt1 *punt2
Alavariablexahorasepuedeaccederde3formas:
x *punt1 *punt2
Luis Hernández Yáñez
¿Apuntanalmismodato?Losoperadoresrelacionales== y!= nospermitensabersidospunterosapuntanaunmismodato:
int x = 5;int *punt1 = NULL;int *punt2 = &x;...if (punt1 == punt2)
cout << "Apuntan al mismo dato" << endl;else
cout << "No apuntan al mismo dato" << endl;
Sólotienesentidocompararpunterosconelmismotipobase.
Página 25Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
14
Luis Hernández Yáñez
Página 26Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
DeclaracióndetiposdepunterosDeclaramostiposparalospunteroscondistintostiposbase:typedef int *intPtr;typedef char *charPtr;typedef double *doublePtr;int entero = 5;intPtr puntI = &entero;char caracter = 'C';charPtr puntC = &caracter;double real = 5.23;doublePtr puntD = ℜcout << *puntI << " " << *puntC << " " << *puntD << endl;
Con*puntero podemoshacerloquesepuedahacerconlosdatosdeltipobasedelpuntero.
Página 27Fundamentos de la programación: Punteros y memoria dinámica
tipos.cpp
13/05/2014
15
Luis Hernández Yáñez
AccesoaestructurasatravésdepunterosLospunterospuedenapuntaracualquiertipodedatos,tambiénestructuras:typedef struct {
int codigo;string nombre;double sueldo;
} tRegistro;tRegistro registro;typedef tRegistro *tRegistroPtr;tRegistroPtr puntero = ®istro;
Operadorflecha(‐>):Permiteaccederaloscamposdeunaestructuraatravésdeunpunterosineloperadordeindirección(*).
puntero‐>codigo puntero‐>nombre puntero‐>sueldo
puntero‐>... (*puntero)....
Página 28Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Accesoaestructurasatravésdepunterostypedef struct {
int codigo;string nombre;double sueldo;
} tRegistro;tRegistro registro;typedef tRegistro *tRegistroPtr;tRegistroPtr puntero = ®istro;registro.codigo = 12345;registro.nombre = "Javier";registro.sueldo = 95000;cout << puntero‐>codigo << " " << puntero‐>nombre
<< " " << puntero‐>sueldo << endl;
puntero‐>codigo (*puntero).codigo *puntero.codigo
Página 29Fundamentos de la programación: Punteros y memoria dinámica
structPtr.cpp
Seesperaríaquepuntero fueraunestructuraconcampocodigo detipopuntero.Seesperaríaquepuntero fueraunestructuraconcampocodigo detipopuntero.
13/05/2014
16
Luis Hernández Yáñez
PunterosaconstantesypunterosconstantesCuandosedeclaranpunterosconelmodificadordeaccesoconst,suefectodependededóndesecoloqueenladeclaración:
const tipo *puntero; Punteroaunaconstante
tipo *const puntero; Punteroconstante
Punterosaconstantes:typedef const int *intCtePtr; // Puntero a dato constante
int entero1 = 5, entero2 = 13;
intCtePtr punt_a_cte = &entero1;
(*punt_a_cte)++; // ERROR: ¡Dato constante no modificable!
punt_a_cte = &entero2; // Sin problema: el puntero no es cte.
Página 30Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
PunterosaconstantesypunterosconstantesPunterosconstantes:typedef int *const intPtrCte; // Puntero constante
int entero1 = 5, entero2 = 13;
intPtrCte punt_cte = &entero1;
(*punt_cte)++; // Sin problema: el puntero no apunta a cte.
punt_cte = &entero2; // ERROR: ¡Puntero constante!
Página 31Fundamentos de la programación: Punteros y memoria dinámica
constPtr.cpp
13/05/2014
17
Luis Hernández Yáñez
Página 32Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
PasodeparámetrosporreferenciaovariableEnellenguajeCnoexisteelmecanismodepasodeparámetroporreferencia(&).Sólosepuedenpasarparámetrosporvalor.
¿Cómoseimplementaentonceselpasoporreferencia?
Pormediodepunteros:
void incrementa(int *punt);
void incrementa(int *punt) {(*punt)++;
}...int entero = 5;incrementa(&entero);cout << entero << endl;
Mostrará6 enlaconsola.
Página 33Fundamentos de la programación: Punteros y memoria dinámica
Pasoporvalor:
Elargumentonosemodificatraslaejecución
(elpuntero nocambia).
PeroaquelloaloqueapuntaSÍ(elentero semodificaatravésdepuntero).
Pasoporvalor:
Elargumentonosemodificatraslaejecución
(elpuntero nocambia).
PeroaquelloaloqueapuntaSÍ(elentero semodificaatravésdepuntero).
param.cpp
13/05/2014
18
Luis Hernández Yáñez
Pasodeparámetrosporreferenciaovariableint entero = 5;incrementa(&entero);
Página 34Fundamentos de la programación: Punteros y memoria dinámica
5enteroentero
puntpunt
6enteroentero
punt recibeladireccióndeenteropunt recibeladireccióndeentero
6enteroentero
void incrementa(int *punt) {(*punt)++;
}
cout << entero << endl;
Luis Hernández Yáñez
Pasodeparámetrosporreferenciaovariable¿Cuáleselequivalenteconpunterosaesteprototipo?¿Cómosellama?void foo(int ¶m1, double ¶m2, char ¶m3);
Prototipoequivalente:
void foo(int *param1, double *param2, char *param3);
void foo(int *param1, double *param2, char *param3) {// Al primer argumento se accede con *param1// Al segundo argumento se accede con *param2// Al tercer argumento se accede con *param3
}
Llamada:int entero; double real; char caracter;//...foo(&entero, &real, &caracter);
Página 35Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
19
Luis Hernández Yáñez
Página 36Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
UnaíntimarelaciónNombredevariablearray Punteroalprimerelementodelarray
Así,sitenemos:int dias[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
Entonces:cout << *dias << endl;
Muestra31 enlaconsola,elprimerelementodelarray.
¡Elnombredelarrayesunpunteroconstante!Siempreapuntaalprimerelemento.Nosepuedemodificarsudirección.
Alrestodeloselementosdelarray,ademásdeporíndice,selespuedeaccederpormediodelasoperacionesaritméticasdepunteros.
Página 37Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
20
Luis Hernández Yáñez
Pasodearraysafunciones¡Estoexplicaporquénousamos&conlosparámetrosarray!Comoelnombredelarrayesunpuntero,yaesunpasoporreferencia.Declaracionesalternativasparaparámetrosarray:const int N = ...;void cuadrado(int array[N]);void cuadrado(int array[], int size); // Array no delimitadovoid cuadrado(int *array, int size); // Puntero
Lastresdeclaracionesdelparámetroarraysonequivalentes.Arraysnodelimitados:Noindicamoseltamaño,pudiendoaceptarcualquierarraydeesetipobase(int).Conarraysnodelimitadosypunterossehadeproporcionarladimensiónparapoderrecorrerelarray.Independientementedecómosedeclareelparámetro,dentrosepuedeaccederaloselementosconíndice(array[i])oconpuntero(*array).
Página 38Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Página 39Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
21
Luis Hernández Yáñez
Página 40Fundamentos de la programación: Punteros y memoria dinámica
RegionesdelamemoriaElS.O.disponeenlamemoriadelacomputadoravariasregionesdondesealmacenandistintascategoríasdedatosdelprograma:
Pila (Stack)
Montón (Heap)
Datos globales
Código del programa
S.O.
DatoslocalesDatoslocales
DatosdinámicosDatosdinámicos
MemoriaprincipalMemoriaprincipal
Luis Hernández Yáñez
Página 41Fundamentos de la programación: Punteros y memoria dinámica
LamemoriaprincipalEnlamemoriaprincipal sealojanlosdatosglobalesdelprograma:losqueestándeclaradosfueradelasfunciones.typedef char tCadena[80];typedef struct {
...} tRegistro;cont int N = 1000;typedef tRegistro tLista[N];typedef struct {
tLista registros;int cont;
} tTabla;
int main() {...
Pila
Montón
Datos globales
Código del programa
S.O.
DatoslocalesDatoslocales
DatosdinámicosDatosdinámicos
MemoriaprincipalMemoriaprincipal
13/05/2014
22
Luis Hernández Yáñez
Página 42Fundamentos de la programación: Punteros y memoria dinámica
Lapila(stack)Enlapila delsistemaseguardanlosdatoslocales:parámetrosporvaloryvariableslocalesdelasfunciones.
void func(tTabla tabla, double &total){tTabla aux;int i;...
Tambiénseguardanlospunterosquesemanejaninternamenteparaapuntaralosargumentosdelosparámetrosporreferencia.
Pila
Montón
Datos globales
Código del programa
S.O.
DatoslocalesDatoslocales
DatosdinámicosDatosdinámicos
MemoriaprincipalMemoriaprincipal
func(tabla, resultado)
&resultado
Luis Hernández Yáñez
Página 43Fundamentos de la programación: Punteros y memoria dinámica
Elmontón(heap)Elmontón esunaenormezonadealmacenamientodondepodemosalojartemporalmentedatosdelprogramaquesecreenysedestruyanamedidaquesenecesitendurantelaejecucióndelprograma.
Datoscreadosdurantelaejecucióndelprograma:Datosdinámicos
Sistemadegestióndememoriadinámica(SGMD):
CuandosenecesitamemoriaparaunavariablesesolicitaéstaalSGMD,quienreservalacantidadadecuadaparaesetipodevariableydevuelveladireccióndelaprimeraceldadememoriadelazonareservada.
Cuandoyanosenecesitamáslavariable,seliberalamemoriaqueutilizabaindicandoalSGMDquepuedecontardenuevoconlamemoriaquesehabíareservadoanteriormente.
Pila
Montón
Datos globales
Código del programa
S.O.
DatoslocalesDatoslocales
DatosdinámicosDatosdinámicos
MemoriaprincipalMemoriaprincipal
13/05/2014
23
Luis Hernández Yáñez
Página 44Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Página 45Fundamentos de la programación: Punteros y memoria dinámica
DatosdinámicosDatosquesecreanysedestruyendurantelaejecucióndelprograma.Selesasignamemoriadelmontón.
¿Porquéutilizarlamemoriadinámica? Esunalmacéndememoriamuygrande:aquellosdatosolistasdedatosquenoquepanenmemoriaprincipal,oqueconsumandemasiadoespacioenlapila,puedenseralojadosenelmontón.
Elprogramaajustaelusodelamemoriaalasnecesidadesdecadamomento:nilefaltaniladesperdicia.
MontónDato dinámico
CreaciónCreación
DestrucciónDestrucción
13/05/2014
24
Luis Hernández Yáñez
Página 46Fundamentos de la programación: Punteros y memoria dinámica
¿Cuándoseasignamemoriaalosdatos?
Datosglobales:Secreanenlamemoriaprincipaldurantelacargadelprograma.Existendurantetodalaejecucióndelprograma.
Datoslocales deunafunción(incluyendoparámetros):Seguardanenlapiladelsistemadurantelaejecucióndeesafunción.Existensólodurantelaejecucióndeesafunción.
Datosdinámicos:Secreanenelmontón(heap)cuandoelprogramalossolicitaysedestruyencuandoelprogramaigualmentelosolicita.Existenavoluntad delprograma.
Luis Hernández Yáñez
Página 47Fundamentos de la programación: Punteros y memoria dinámica
Datosestáticos Constantesyvariablesdeclaradascomodeuntipoconcreto:int i;
Suinformaciónseaccededirectamenteatravésdelidentificador:cout << i;
Datosdinámicos Constantesyvariablesaccedidasatravésdesudireccióndememoria.
Senecesitatenerguardadaesadireccióndememoriaenalgúnsitio:Puntero.
Yahemosvistoquelosdatosestáticostambiénsepuedenaccederatravésdepunteros(int *p = &i;).
13/05/2014
25
Luis Hernández Yáñez
Página 48Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Página 49Fundamentos de la programación: Punteros y memoria dinámica
Operadores new y deleteHastaahorahemostrabajadoconpunterosquecontienendireccionesdedatosestáticos(variablesenmemoriaprincipaloenlapila).
Sinembargo,lospunterostambiénsonlabasesobrelaqueseapoyaelsistemadegestióndinámicadememoria.
Cuandoqueremoscrearunavariabledinámicadeuntipodeterminado,pedimosmemoriadelmontónconeloperadornew.
Eloperadornew reservalamemorianecesariaparaesetipodevariableydevuelveladireccióndelaprimeraceldadememoriaasignadaalavariable;esadirecciónseguardaenunpuntero.
Cuandoyanonecesitemoslavariable,devolvemoslamemoriaqueutilizaalmontónmedianteeloperadordelete.
Aloperadorselepasaunpunteroconladireccióndelaprimeraceldadememoria(delmontón)utilizadaporlavariable.
13/05/2014
26
Luis Hernández Yáñez
Página 50Fundamentos de la programación: Punteros y memoria dinámica
Eloperadornewnew tipo Reservamemoriadelmontónparaunavariablede
esetipo ydevuelvelaprimeradireccióndememoriautilizada,quedebeserasignadaaunpuntero.
int *p; // Todavía sin una dirección válidap = new int; // Ya tiene una dirección válida*p = 12;
Lavariabledinámicaseaccedeexclusivamenteatravésdepunteros;nohayningúnidentificadorasociadoconellaquepermitaaccederla.int i; // i es una variable estáticaint *p1, *p2;p1 = &i; // Puntero que da acceso a la variable
// estática i (accesible con i o con *p1)p2 = new int; // Puntero que da acceso a una variable
// dinámica (accesible sólo a través de *p2)
Luis Hernández Yáñez
Página 51Fundamentos de la programación: Punteros y memoria dinámica
Eloperadordeletedelete puntero; Devuelvealmontónlamemoriautilizadapor
lavariabledinámicaapuntadaporpuntero.int *p;p = new int;*p = 12;...delete p; // Ya no se necesita el entero apuntado por p
Elpunterodejadecontenerunadirecciónválidaynosedebeaccederatravésdeélhastaquenocontenganuevamenteotradirecciónválida.
13/05/2014
27
Luis Hernández Yáñez
Montón(heap)Montón(heap)
Página 52Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;cout << *p1 << endl;cout << *p2 << endl;cout << *p3 << endl;delete p2;delete p3;
return 0;}
dinamicas.cpp
1.5aa
p1p1
p2p2
p3p3
Identificadores:
4(a,p1,p2,p3)
Variables:
6(+*p2 y*p3)
Identificadores:
4(a,p1,p2,p3)
Variables:
6(+*p2 y*p3)
1.51.5
123.45123.45
Luis Hernández Yáñez
Página 53Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;
PILA
a 1.5
p1 ?
p2 ?
p3 ?
MONTÓN
13/05/2014
28
Luis Hernández Yáñez
Página 54Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;
PILA
a 1.5
p1
p2 ?
p3 ?
MONTÓN
Luis Hernández Yáñez
Página 55Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;
PILA
a 1.5
p1
p2
p3 ?
MONTÓN
13/05/2014
29
Luis Hernández Yáñez
Página 56Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;
PILA
a 1.5
p1
p2
p3 ?
1.5
MONTÓN
Luis Hernández Yáñez
Página 57Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;
PILA
a 1.5
p1
p2
p3
1.5
MONTÓN
13/05/2014
30
Luis Hernández Yáñez
Página 58Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;
PILA
a 1.5
p1
p2
p3
123.45
1.5
MONTÓN
Luis Hernández Yáñez
Página 59Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;cout << *p1 << endl;cout << *p2 << endl;cout << *p3 << endl;delete p2;
PILA
a 1.5
p1
p2 ?
p3
123.45
MONTÓN
13/05/2014
31
Luis Hernández Yáñez
Página 60Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodevariablesdinámicas#include <iostream>using namespace std;
int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;cout << *p1 << endl;cout << *p2 << endl;cout << *p3 << endl;delete p2;delete p3;
PILA
a 1.5
p1
p2 ?
p3 ?
MONTÓN
Luis Hernández Yáñez
Página 61Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
32
Luis Hernández Yáñez
Página 62Fundamentos de la programación: Punteros y memoria dinámica
ErroresdeasignacióndememoriaParaaprovecharbienlamemoriaquedejalibrelamemoriaprincipal,lapilayelmontóncrecenendireccionesopuestas.
Amedidaquesellamaafuncioneslapilacrece.
Amedidaquesecreandatosdinámicoselmontóncrece.
Siloslímitesdeambasregionesdememoriaseencuentran,seproduceunacolisiónpila‐montón.
Elprogramafallaporquenosepuedencrearmásdatosdinámicosnisepuedenrealizarmásllamadasafunciones.
Normalmentelapilasueleteneruntamañomáximoestablecidoquenopuedesobrepasaraunqueelmontónnoestéutilizandoelresto.Silosobrepasaloqueseproduceesundesbordamientodelapila.
Pila
Montón
Luis Hernández Yáñez
Página 63Fundamentos de la programación: Punteros y memoria dinámica
GestióndelmontónElSistemadeGestióndeMemoriaDinámica(SGMD)seencargadelocalizarenelmontónunbloquesuficientementegrandeparaalojarlavariablequesepidacrearysiguelapistadelosbloquesdisponibles.
Peronodisponedeunrecolectordebasura,comoellenguajeJava.
Esnuestraresponsabilidaddevolveralmontóntodalamemoriautilizadapornuestrasvariablesdinámicasunavezquenosenecesitan.
Losprogramasdebenasegurarsededestruir,coneloperadordelete,todaslasvariablespreviamentecreadasconeloperadornew.
Lacantidaddememoriadisponibleenelmontóndebeserexactamentelamismaantesydespuésdelaejecucióndelprograma.
Ysiempredebehaberalgunaforma(puntero)deaccederacadadatodinámico.Esungraveerrorperder undatoenelmontón.
13/05/2014
33
Luis Hernández Yáñez
Página 64Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Página 65Fundamentos de la programación: Punteros y memoria dinámica
InicializaciónconeloperadornewEloperadornew admiteunvalorinicialparaeldatodinámicocreado:int *p;p = new int(12);
Secrealavariabledinámica,detipoint,yseinicializaconelvalor12.#include <iostream>using namespace std;#include "registro.h"
int main() {tRegistro reg;reg = nuevo();tRegistro *punt = new tRegistro(reg);mostrar(*punt);delete punt;return 0;
}
registros.cpp
13/05/2014
34
Luis Hernández Yáñez
Página 66Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
Página 67Fundamentos de la programación: Punteros y memoria dinámica
MalusodelamemoriadinámicaIOlvidodedestruccióndeundatodinámico:...int main() {
tRegistro *p;p = new tRegistro;*p = nuevo();mostrar(*p);
return 0;}
G++nodaráningunaindicacióndelerroryelprogramapareceráterminarcorrectamente,perodejarámemoriadesperdiciada.
VisualC++sícompruebaelusodelamemoriadinámicaynosavisasidejamosmemoriasinliberar.
Faltadelete p;Faltadelete p;
13/05/2014
35
Luis Hernández Yáñez
Página 68Fundamentos de la programación: Punteros y memoria dinámica
MalusodelamemoriadinámicaIIIntentodedestruccióndeundatodinámicoinexistente:...int main() {
tRegistro *p1 = new tRegistro;*p1 = nuevo();mostrar(*p1);tRegistro *p2;p2 = p1;mostrar(*p2);delete p1;delete p2;
return 0;}
tRegistrop1p1
p2p2
Sólosehacreadounavariabledinámica Nosepuedendestruir2
Sólosehacreadounavariabledinámica Nosepuedendestruir2
Luis Hernández Yáñez
¡Perdido!
Página 69Fundamentos de la programación: Punteros y memoria dinámica
MalusodelamemoriadinámicaIIIPérdidadeundatodinámico:...int main() {
tRegistro *p1, *p2;p1 = new tRegistro(nuevo());p2 = new tRegistro(nuevo());
mostrar(*p1);p1 = p2;mostrar(*p1);
delete p1;delete p2;
return 0;}
tRegistrop2p2
p1p1
p1 dejadeapuntaraldatodinámicoquesecreóconél Sepierdeesedatoenelmontón
p1 dejadeapuntaraldatodinámicoquesecreóconél Sepierdeesedatoenelmontón
tRegistro
13/05/2014
36
Luis Hernández Yáñez
Página 70Fundamentos de la programación: Punteros y memoria dinámica
MalusodelamemoriadinámicaIVIntentodeaccesoaundatodinámicotrassueliminación:...int main() {
tRegistro *p;p = new tRegistro(nuevo());
mostrar(*p);delete p;...mostrar(*p);
return 0;}
p hadejadodeapuntaraldatodinámicodestruido Intentodeaccesoamemoriainexistentep hadejadodeapuntaraldatodinámicodestruido Intentodeaccesoamemoriainexistente
Luis Hernández Yáñez
Página 71Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
37
Luis Hernández Yáñez
Página 72Fundamentos de la programación: Punteros y memoria dinámica
Arraysdepunterosadatosdinámicostypedef char tCadena[80];typedef struct {
int codigo;tCadena nombre;double valor;
} tRegistro;typedef tRegistro *tRegPtr;
const int N = 1000;
// Array de punteros a registros:typedef tRegPtr tArray[N];typedef struct {
tArray registros;int cont;
} tLista;
Lospunterosocupanmuypocoenmemoria.
Losdatosalosqueapuntenseguardaránenelmontón.
Secrearánamedidaqueseinsertenenlalista.
Sedestruiránamedidaqueseeliminendelalista.
Lospunterosocupanmuypocoenmemoria.
Losdatosalosqueapuntenseguardaránenelmontón.
Secrearánamedidaqueseinsertenenlalista.
Sedestruiránamedidaqueseeliminendelalista.
Luis Hernández Yáñez
Página 73Fundamentos de la programación: Punteros y memoria dinámica
ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;
0 1 2 3 4 5 6 998 999
lista.registroslista.registros
0lista.contlista.cont
13/05/2014
38
Luis Hernández Yáñez
Página 74Fundamentos de la programación: Punteros y memoria dinámica
ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;
0 1 2 3 4 5 6 998 999
lista.registroslista.registros
1lista.contlista.cont
Luis Hernández Yáñez
Página 75Fundamentos de la programación: Punteros y memoria dinámica
ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;
0 1 2 3 4 5 6 998 999
lista.registroslista.registros
2lista.contlista.cont
13/05/2014
39
Luis Hernández Yáñez
Página 76Fundamentos de la programación: Punteros y memoria dinámica
ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;
0 1 2 3 4 5 6 998 999
lista.registroslista.registros
3lista.contlista.cont
Luis Hernández Yáñez
Página 77Fundamentos de la programación: Punteros y memoria dinámica
ArraysdepunterosadatosdinámicosLosregistrosseaccedenatravésdepunteros(operadorflecha):cout << lista.registros[0]‐>nombre;
0 1 2 3 4 5 6 998 999
lista.registroslista.registros
3lista.contlista.cont
13/05/2014
40
Luis Hernández Yáñez
Página 78Fundamentos de la programación: Punteros y memoria dinámica
ArraysdepunterosadatosdinámicosNohayqueolvidarsededevolverlamemoriaalmontón:for (int i = 0; i < lista.cont; i++)
delete lista.registros[i];
0 1 2 3 4 5 6 998 999
lista.registroslista.registros
3lista.contlista.cont
Luis Hernández Yáñez
Página 79Fundamentos de la programación: Punteros y memoria dinámica
Implementacióndelalistadinámica#ifndef LISTA_H#define LISTA_H#include "registro.h"
const int N = 1000;typedef tRegPtr tArray[N];typedef struct {
tArray registros;int cont;
} tLista;
const char BD[] = "bd.dat";
void mostrar(const tLista &lista);bool insertar(tLista &lista, tRegistro registro);bool eliminar(tLista &lista, int code);int buscar(tLista lista, int code);bool cargar(tLista &lista);void guardar(tLista lista);void destruir(tLista &lista);
#endif
lista.h
13/05/2014
41
Luis Hernández Yáñez
Implementacióndelalistadinámica...bool insertar(tLista &lista, tRegistro registro) {
bool ok = true;if (lista.cont == N) ok = false;else {
lista.registros[lista.cont] = new tRegistro(registro);lista.cont++;
}return ok;
}
bool eliminar(tLista &lista, int code) {bool ok = true;int ind = buscar(lista, code);if (ind == ‐1) ok = false;else {
delete lista.registros[ind];for (int i = ind + 1; i < lista.cont; i++)
lista.registros[i ‐ 1] = lista.registros[i];lista.cont‐‐;
}return ok;
} ...
Página 80Fundamentos de la programación: Punteros y memoria dinámica
lista.cpp
Luis Hernández Yáñez
Página 81Fundamentos de la programación: Punteros y memoria dinámica
Implementacióndelalistadinámicaint buscar(tLista lista, int code) {// Devuelve el índice o ‐1 si no se ha encontrado
int ind = 0;bool encontrado = false;while ((ind < lista.cont) && !encontrado)
if (lista.registros[ind]‐>codigo == code) encontrado = true;else ind++;
if (!encontrado) ind = ‐1;return ind;
}
void mostrar(const tLista &lista) {cout << endl << "Elementos de la lista:" << endl
<< "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐" << endl;for (int i = 0; i < lista.cont; i++)
mostrar(*lista.registros[i]);}
void destruir(tLista &lista) {for (int i = 0; i < lista.cont; i++)
delete lista.registros[i];lista.cont = 0;
} ...
13/05/2014
42
Luis Hernández Yáñez
Página 82Fundamentos de la programación: Punteros y memoria dinámica
Implementacióndelalistadinámica#include <iostream>using namespace std;#include "registro.h"#include "lista.h"
int main() {tLista lista;if (cargar(lista)) {
mostrar(lista);destruir(lista);
}
return 0;}
listadinamica.cpp
Luis Hernández Yáñez
Página 83Fundamentos de la programación: Punteros y memoria dinámica
13/05/2014
43
Luis Hernández Yáñez
Página 84Fundamentos de la programación: Punteros y memoria dinámica
DestruccióndelarraydinámicoDestruccióndelarraydinámico
CreaciónydestruccióndearraysdinámicosUnarraydinámicoesunarraydedatosdinámicosparaelquesecreantodoslosdatosdinámicosautomáticamentealdeclararlo:int *p = new int[10];
Secreanlas10variablesdinámicas,detipoint.Seaccedenconp[i].#include <iostream>using namespace std;const int N = 10;
int main() {int *p = new int[N];for (int i = 0; i < N; i++) p[i] = i;for (int i = 0; i < N; i++) cout << p[i] << endl;delete [] p;
return 0;}
Luis Hernández Yáñez
Página 85Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodearraydinámico...#include "registro.h"
const int N = 1000;
// Lista: array dinámico y contadortypedef struct {
tRegPtr registros;int cont;
} tLista;
...
listaAD.h
13/05/2014
44
Luis Hernández Yáñez
Página 86Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodearraydinámico
bool insertar(tLista &lista, tRegistro registro) {
bool ok = true;
if (lista.cont == N) ok = false;
else {
lista.registros[lista.cont] = registro;
lista.cont++;
}
return ok;
}
bool eliminar(tLista &lista, int code) {
bool ok = true;
int ind = buscar(lista, code);
if (ind == ‐1) ok = false;
else {
for (int i = ind + 1; i < lista.cont; i++)
lista.registros[i ‐ 1] = lista.registros[i];
lista.cont‐‐;
}
return ok;
} ...
listaAD.cpp
Nousamosnew,puessehancreadotodoslosregistrosanteriormente
Nousamosnew,puessehancreadotodoslosregistrosanteriormente
Nousamosdelete,puessedestruyentodoslosregistrosalfinal
Nousamosdelete,puessedestruyentodoslosregistrosalfinal
Luis Hernández Yáñez
Página 87Fundamentos de la programación: Punteros y memoria dinámica
Usamospuntoenlugarde‐>Usamospuntoenlugarde‐>
AccesocomoarrayAccesocomoarray
SedestruyentodosalavezSedestruyentodosalavez
Ejemplodearraydinámico
int buscar(tLista lista, int code) {
int ind = 0;
bool encontrado = false;
while ((ind < lista.cont) && !encontrado)
if (lista.registros[ind].codigo == code) encontrado = true;
else ind++;
if (!encontrado) ind = ‐1;
return ind;
}
void mostrar(const tLista &lista) {
cout << endl
<< "Elementos de la lista:" << endl
<< "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐" << endl;
for (int i = 0; i < lista.cont; i++)
mostrar(lista.registros[i]);
}
void destruir(tLista &lista) {
delete [] lista.registros;
lista.cont = 0;
} ...
13/05/2014
45
Luis Hernández Yáñez
Página 88Fundamentos de la programación: Punteros y memoria dinámica
SecreantodosalavezSecreantodosalavez
Ejemplodearraydinámicobool cargar(tLista &lista) {
bool ok = true;ifstream archivo;archivo.open(BD);if (!archivo.is_open()) ok = false;else {
tRegistro registro;lista.cont = 0;lista.registros = new tRegistro[N];archivo >> registro.codigo;while ((registro.codigo != ‐1) && (lista.cont < N)) {
archivo >> registro.valor;archivo.getline(registro.nombre, 80);lista.registros[lista.cont] = registro;lista.cont++;archivo >> registro.codigo;
}archivo.close();
} ...
Luis Hernández Yáñez
Página 89Fundamentos de la programación: Punteros y memoria dinámica
Ejemplodearraydinámicovoid guardar(tLista lista) {
ofstream archivo;archivo.open(BD);for (int i = 0; i < lista.cont; i++) {
archivo << lista.registros[i].codigo << " ";archivo << lista.registros[i].valor;archivo << lista.registros[i].nombre << endl;
}archivo.close();
}
Mismoprogramaprincipalqueeldelarraydedatosdinámicos,peroincluyendolistaAD.h,enlugardelista.h.
ejemploAD.cpp
13/05/2014
46
Luis Hernández Yáñez
Página 90Fundamentos de la programación: Punteros y memoria dinámica
Losarraysdedatosdinámicosvantomandodelmontónmemoriaamedidaquelanecesitan,mientrasqueelarraydinámicosecreaenteroenelmontón:
Montón
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7
Arraydedatosdinámicos:Arraydepunteros
Arraydedatosdinámicos:Arraydepunteros
Arraydinámico:Puntero(direccióndearray)
Arraydinámico:Puntero(direccióndearray)
Luis Hernández Yáñez
C++:An Introduction to Computing (2ªedición)J.Adams,S.Leestma,L.Nyhoff.Prentice Hall,1998
EllenguajedeprogramaciónC++ (Ediciónespecial)B.Stroustrup.Addison‐Wesley,2002
ProgramaciónenC++paraingenierosF.Xhafa etal.Thomson,2006
Fundamentos de la programación: Punteros y memoria dinámica Página 91
13/05/2014
47
Luis Hernández Yáñez
LicenciaCC(Creative Commons)Estetipodelicenciasofrecenalgunosderechosaterceraspersonasbajociertascondiciones.
Estedocumentotieneestablecidaslassiguientes:
Pulsaenlaimagendearribaaladerechaparasabermás.
Fundamentos de la programación: Punteros y memoria dinámica Página 92
Reconocimiento(Attribution):Encualquierexplotacióndelaobraautorizadaporlalicenciaharáfaltareconocerlaautoría.
Nocomercial(Noncommercial):Laexplotacióndelaobraquedalimitadaausosnocomerciales.
Compartirigual(Sharealike):Laexplotaciónautorizadaincluyelacreacióndeobrasderivadassiemprequemantenganlamismalicenciaalserdivulgadas.