Você está na página 1de 5

Facultad de Informática, Electrónica y Comunicación

Estructuras de datos -Inf200 e Inf212


Apuntadores

Punteros o apuntadores o pointers


Un puntero es una variable que contiene una dirección de memoria. Normalmente, esa dirección
es la posición de otra variable en la memoria. Si la variable p de tipo float, está en la dirección 1111 y la
variable ptr en la dirección 1021, entonces, si el contenido de ptr es la dirección de p, es decir 1111,
decimos que ptr es un apuntador a p.
p
ptr 1021 1111

1111 45.23

Algunas consideraciones para utilizar punteros o apuntadores:


 Existen dos operadores especiales de punteros: & y *. El operador de dirección (&)
devuelve la dirección de memoria de su operando. El operador de indirección (*)
devuelve el contenido de la dirección apuntada por el operando.
 Los punteros apuntan a un tipo de variable, el cual se define en la declaración, por
ejemplo;
 int *ptr1; /* apunta solo a variables tipo int */
 float *ptr; /* apunta solo a variables tipo float */
 char *prt2; /* apunta solo a variable tipo char */
 El operador de dirección & delante del nombre de una variable nos devuelve la dirección
de la variable, ejemplo;
 int a; ptr1 = &a;
 float p, q; ptr = &p;
 El valor apuntado por un puntero se obtiene con el operador de indirección *. Si usamos
la ilustración anterior *ptr corresponde al valor 45.23 de la variable p. Si hacemos q =
*ptr; entonces q y p tienen el mismo valor, pero ptr no apunta a q, sino a p.
 En conclusión, si ptr contiene la dirección de memoria de la variable p, entonces ptr
apunta a p y *ptr indica el contenido de p, es decir, cuando se modifica o cambia el valor
de *ptr se cambia también el valor de la variable p. Concretamente si hacemos *ptr =
100; entonces, el valor de la variable p también es 100. Todo esto se da porque ptr a
punta a p o de manera equivalente, porque ptr contiene la dirección de p.

De manera general una declaración de un puntero consiste en un tipo base(int, char, flotat), un
asterisco * y el nombre de la variable. La forma general es:
tipo *nombre_de _variable;

Se pueden declarar apuntadores a una estructura:


typedef struct {
int edad;
float salario; /* declaración de tipo estructura global */
char nom[15];
}xxx;

xxx *ptr3; /* apuntador al tipo de estructura xxx */

Diego Santimateo G. / Giannina Núñez M. 1


Facultad de Informática, Electrónica y Comunicación
Estructuras de datos -Inf200 e Inf212
Apuntadores

Asignación de punteros
Como en el caso de cualquier otra variable, un puntero puede utilizarse a la derecha de una
declaración de asignación para asignar su valor a otro puntero. Por ejemplo:
int x;
int *p1,*p2;
p1=&x;
p2=p1;
Tanto p1 como p2 apuntan a x.

Operaciones con punteros


Existen sólo dos operaciones aritméticas que se pueden usar con punteros: la suma y la resta.
Cada vez que se incrementa en una unidad un puntero, apunta a la posición de memoria del siguiente
elemento de su tipo base(int, flota, char). Cada vez que se disminuye en una unidad, apunta a la posición
del elemento anterior. Con punteros a variables del tipo char(un byte) parece una aritmética normal, sin
embargo, el resto de los punteros aumentan o decrecen dependiendo de la longitud del tipo de datos a
los que apuntan, piense en el tamaño de un registro. Por ejemplo, si asumimos que los enteros son de
dos bytes de longitud y p1 es un puntero a entero con valor actual 2000. Entonces, después de la
expresión p1++; p1 contiene el valor 2002, no 2001.
Las variables punteros pueden ser comparadas siempre que éstas apunten a un mismo tipo de
datos, por ejemplo;
Int *ptr1, *ptr2;
Podemos usar las siguientes expresiones lógicas:
 ptr1 < ptr2 ptr2 >= ptr1
 ptr1 == ptr2 ptr2 != ptr1
 ptr == NULL

Punteros y arrays
Existe una estrecha relación entre los punteros y los arreglos. Recuerde que el nombre de un
arreglo se considera puntero a la primera posición.
char linea[80], *prt2;
prt2 = linea;
Aquí, prt2 ha sido asignado a la dirección del primer elemento del vector linea. Para acceder al
quinto elemento de linea se escribe linea[4] o *(prt2 + 4). Los punteros pueden almacenarse en arreglos
como cualquier otro tipo de datos. Por ejemplo, para un arreglo de 10 punteros a tipo entero, la
declaración es: int *x[10]; Para asignar la dirección de una variable entera llamada var al tercer
elemento de x se escribe: x[2] = &var; El valor de la variable var corresponde a *x[2];(valor que es
apuntado por x[2]).

Indirección múltiple
Se puede hacer que un puntero apunte a otro puntero que apunte a un valor de destino. Esta
situación se denomina indirección múltiple o punteros a punteros. Una variable que es puntero a puntero
tiene que declararse como tal. Esto se hace colocando un asterisco (*) adicional en frente del nombre de
la variable. Por ejemplo, la siguiente declaración indica al compilador que ptr es un puntero a puntero de
tipo float:
float **ptr;

Funciones de asignación dinámica, malloc() y free()


Hasta el momento hemos trabajado con estructuras de datos estáticas, no obstante los punteros
proporcionan el soporte necesario para manejar estructuras de datos dinámica en C. La asignación
dinámica es la forma en la que un programa puede obtener memoria mientras se está ejecutando y
también puede liberarla cuando sea necesario.

Diego Santimateo G. / Giannina Núñez M. 2


Facultad de Informática, Electrónica y Comunicación
Estructuras de datos -Inf200 e Inf212
Apuntadores

El centro del sistema de asignación dinámica está compuesto por las funciones (existentes en la
biblioteca stdlib.h)
 malloc(), que asigna memoria y devuelve un puntero a un char.
 free() que la devuelve o la libera.

Podemos invocar a la función malloc() así:


ptr =malloc( n * sizeof(tipo de dato));

Tras una llamada fructífera, malloc() devuelve un puntero a un caracter, de manera que en el
ejemplo, la declaración de ptr es char *ptr. Si no hay suficiente memoria libre para satisfacer la petición
de malloc(), se devuelve el apuntador nulo. En el siguiente código se asigna en tiempo de ejecución 10
posiciones enteras (un vector de 10 posiciones)
int *ptr2;
ptr2 = (int *) malloc(50 * sizeof(int));

Nótese que se ha hecho una conversión del tipo char que devuelve malloc, a tipo int de ptr2. Después de
la asignación, ptr2 apunta a la primera posición entera de las 50 solicitadas.

La función free() es la opuesta de malloc() porque devuelve al sistema la memoria previamente


asignada. Una vez que la memoria ha sido liberada, puede ser reutilizada en una posterior llamada a
malloc(). El prototipo de la función free() es:
void free (void *p);
free(p);

Listas dinámicas
Si se desea crear una lista dinámica cuyos nodos contengan diferentes tipos de datos, entonces,
es necesario definir una estructura o registro que contenga un apuntador para ir enlazando los nodos, tal
como se muestra en el diagrama:

inf. sig inf. sig inf. sig inf sig

Inicio

Null

Nodo1 Nodo2 Nodo3 Nodo4

La siguiente declaración se ajusta al diagrama:

struct elementonodo {
int inf;
struct elementonodo *sig;

};
typedef struct elementonodo nodo; /* nodo es un tipo de estructura */

nodo *inicio, *ptr; / declara apuntadores al tipo nodo */

Diego Santimateo G. / Giannina Núñez M. 3


Facultad de Informática, Electrónica y Comunicación
Estructuras de datos -Inf200 e Inf212
Apuntadores

Para crear cada nodo se usa:


ptr = (nodo * ) malloc (sizeof(nodo)); /* reserva espacio para un nodo */
La primera vez inicio = ptr;
Podemos acceder a un campo de la estructura así:
ptr -> inf = 100;
ptr -> sig = NULL;
¿Cómo hacer para ir añadiendo nodos a la lista? ... escriba el código necesario.

Ejemplos de uso de la función malloc


#include <stdio.h>
#include <stdlib.h>
void main()
{
int *pint;
float *preal;
char *pcar;

typedef struct{
int num;
char nombre[10];
} estructura;

estructura *pestr; // apuntador a tipo estructura

struct datos{ //estructura que incluye un puntero


int num;
char nombre[10];
struct datos *liga;
};
typedef struct datos nodo;
nodo *nuevo;
// crea área de memoria para un entero
pint = (int *)malloc (sizeof(int));
scanf ("%d", pint);
printf ("%d\n", *pint);

pcar = (char *)malloc(sizeof(char));


*pcar = 'a';
printf("%c\n",*pcar);

preal = (float *)malloc(sizeof(float));


scanf ("%f",preal);
printf("%f\n",*preal);
// crea área para un tipo estructura
pestr = (estructura *)malloc(sizeof(estructura));
scanf ("%d",&pestr->num);
printf("%d\n",pestr->num);

scanf ("%s",pestr->nombre);
printf("%s\n",pestr->nombre);

nuevo = (nodo *)malloc(sizeof(nodo));


scanf ("%d",&nuevo->num);

Diego Santimateo G. / Giannina Núñez M. 4


Facultad de Informática, Electrónica y Comunicación
Estructuras de datos -Inf200 e Inf212
Apuntadores

printf("%d\n",nuevo->num);

scanf ("%s",nuevo->nombre);
printf("%s\n",nuevo->nombre);
nuevo ->liga = NULL;

printf ("\n fin");


}

Diego Santimateo G. / Giannina Núñez M. 5

Você também pode gostar