fundamentos de la programación 2013 2014 9 · al copiarle otro puntero (con el mismo tipo base)...

Post on 31-Jul-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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 = &real;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 = &registro;

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 = &registro;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 &param1, double &param2, char &param3);

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.

top related