Tipo Puntero l 2.3.3 Tipo Puntero l Operaciones, problemas de uso, tipo referencia e implementación l Operaciones con Punteros l l l l 7023 432 432 2145 ptr Operador * en C y C++ (e.g. *ptr) Operador ^ en Pascal (e.g. ptr^) Aritmética de punteros en C y C++ Problema con Punteros l Ejemplo en C Asignación: asigna a la variable como valor una dirección a algún objeto de memoria. Desreferenciación: entrega el valor del objeto apuntado. l Œ Dejar colgado (dangling) int j, * ptr; 7127 ptr= ( int*) malloc( sizeof( int)); *ptr = 432; j = *ptr; j Problema con Punteros l typedef tipo* ptipo; tipo x; ptipo p, q; p= (ptipo) malloc(sizeof(tipo)); ... q= p; ... free(p); ... /* puede que la variable de heap sea reasignada */ *q = x; Su valor corresponde a una dirección de memoria, habiendo un valor especial nulo (nil) que no apunta a nada. Aplicaciones: l ŒMétodo de gestión dinámica de memoria (acceso a variables dinámicas de heap) l •Método de direccionamiemto indirecto No corresponde a un tipo estructurado, aun cuando se definen en base a un operador de tipo •Pérdida de variables dinámicas de heap tipo* p; p= (tipo *) malloc(sizeof(tipo)); ... p= ( ptipo *) malloc(sizeof(tipo)); /* se pierde la variable asignada anteriormente */ l Se pierde el acceso a la variable, convirtiéndose en basura dado que no puede ser reasignada 1 Punteros y Arreglos en C y C++ Punteros y Estructuras en C y C++ struct nodo_t { tipodato info; struct nodo_t *siguiente; }; typedef nodo_t* enlace_t; Autoreferencia l Un arreglo es en realidad una constante de tipo puntero enlace_t nodo; int a[10]; int *pa; #ifndef C++ nodo = (enlace_t) malloc(sizeof(nodo_t)); #elif nodo = new nodo_t; /* caso C++ */ #endif (*nodo).info = dato; pa = &a[0]; pa = a; /* hace lo mismo que la linea anterior */ for (int i=0; i<10; i++) for (int i=0; i<10; i++) for (int i=0; i<10; i++) /* los tres for hacen lo /* forma más conveniente de referirse es */ nodo->siguiente = NULL; Aritmética de Punteros en C y C++ #define ALLOCSIZE 1000 /* tamaño del buffer */ static char allocbuf[ALLOCSIZE]; /* el buffer */ static char* allocp = allocbuf; /* primera posición libre */ char *alloc(int n) / retorna puntero a “n” caracteres */ { if (allocbuf + ALLOCSIZE – allocp >= n) { /*si cabe */ allocp += n; return allocp – n; /* antigua direccion */ } else return 0; } Tipo Referencia en C++ l l Un tipo referencia es una variable tipo puntero constante que es implícitamente desreferenciada. Dado que es constante, debe ser inicializada en su definición. int valor = 3; int &ref_valor = valor; ref_valor = 100; void afree (char *p) { if (p >= allocbuf && p < allocbuf + ALLOCSIZE) allocp = p; } Referencias en Java l Java extiende la forma de variables de referencia de C++, haciendo innecesario y, por lo tanto, eliminando el uso de punteros. l l l l Java permite asignar un nuevo objeto a una variable de referencia Todo objeto sólo se referencia con estas variables En Java liberación de objetos es implícita Requiere de un recolector de basura printf(a[i]); printf(*(pa+i)); printf(*(a+i)); mismo */ l /* ahora valor == 100 */ La referencia actúa como alias de una variable. Métodos de Reclamo de Basura l Contadores de Referencia (impaciente) l l l l Se mantiene un contador de referencia por cada celda Se incrementa con una nueva referencia y se decrementa cuando se pierde una referencia Celda se libera tan pronto cuenta llega a cero (cuando se convierte en basura) Recolección de Basura (perezoso) l l Se acumula basura hasta que se agota la memoria Si se agota la memoria se identifican las celdas de basura y se pasan a la lista de celdas libres 2 Recolección de Basura void* allocate (int n) { if (!hay_espacio) { /* recolectar basura */ 1) marcar todo los objetos del heap como basura; 2) for (todo puntero p ) { if (p alcanza objeto o en el heap) marcar o como NO basura; } /* for */ 3) liberar todos los objetos marcados como basura } if (hay_espacio) { asignar espacio; return puntero al objeto; } else return NULL; Evaluación de los Métodos l Contadores de referencia l l l Requiere bastante memoria para mantener contadores Asignaciones a punteros requiere de más tiempo de ejecución para mantener contadores Recolección de basura l l Basta un bit por celda para marcar basura Mal desempeño cuando queda poca memoria } 3