Está en la página 1de 21

Punteros

Índice
1. Qué es un puntero y por que son
importantes.
2. Punteros a tipos básicos.
3. Punteros sin tipo.
4. Memoria dinámica.
5. Punteros a estructuras.
6. Punteros a matrices.
7. Punteros a punteros a punteros….
8. Punteros a funciones.

1
Qué es un puntero y por
qué son importantes

Introducción

En Java existen punteros y reserva


dinámica de memoria !!!!!!!.

Lo que no existe es aritmética de


punteros ni liberación de memoria
dinámica.

2
Introducción
¿Alguien se atreve a definir lo que es
un puntero?.
Un puntero es una variable capaz de almacenar
direcciones de memoria y mediante los operadores
adecuados acceder a la información que contiene la
dirección de memoria a la que “apunta” en cada momento.

¿Alguien puede decir esto con otras


palabras?. ¿Y hacer un dibujo?.

Introducción
‹ ¿Por
qué son importantes los
punteros?.
– Tablas y cadenas.
– Parámetros por referencia.
– Biblioteca de funciones (scanf).
– Coger la memoria que necesitamos.

3
Introducción
‹ ¿Cuáles son los peligros / errores
típicos con punteros?.
– Olvidarnos de reservar memoria.
– Olvidarnos de devolver memoria.
– Apuntar a dónde no es.
– No utilizar el operador adecuado (*, &).

Punteros a tipos
básicos

4
Punteros a tipos básicos
‹ Así se declaran punteros:
int *a; // puntero a entero
char *c; // puntero a caracter

‹C necesita saber el tipo apuntado


para poder manipularlo.
‹ ¿Qué guarda la variable a, y la
variable c justo después de
declararla?

Punteros a tipos básicos


‹2 operadores:
– * : valor apuntado
– & : dirección de memoria.

int *a;
….
a
*a ¿Cuál es la diferencia
(un dibujo)?
&a

5
Punteros a tipos básicos
‹ ¿Cómo podemos declarar un puntero
que apunte al número 3?.
int *a;

*a = 3;

Mal !!!!!

‹ ¿Y por qué?.

Punteros a tipos básicos


‹ Una primera solución.
int *a;
int b = 3;

a = &b;

‹ Un dibujo.

6
Punteros a tipos básicos
Ejemplos de uso de operadores de punteros.
Se declaran dos variable enteras “i” y “j” y un puntero a entero “p”
int i, j, *p;
Suponemos que “i” y “j” se ubican en las direcciones 13B6 e 5FC4,
respectivamente.
Contenido
operación Variable de la memoria
i=15; i 13B6 15
?
p=&i; (p “apunta” a i)
j 5FC4 15
?
j=*p; (se accede a lo
apuntado por p) p ? 13B6
?

Punteros y constantes
‹ Punteros y constantes:
const int*
int* a;
‹ Puntero a una constante. Puede
cambiar el puntero pero no puede
cambiar el valor apuntado.
int*
int* const a = [Dirección de memoria];
‹ Puntero constante. Puede cambiar el
valor pero no la dirección de
memoria.

7
Punteros
‹ En C también tenemos NULL.
‹ Ojo, se escribe todo en mayúsculas y
NO es una palabra reservada.
‹ ¿Para qué utilizamos NULL?.

int *a = NULL;
….
if (a == NULL) {
printf(“a no apunta a ningún sitio ”);
}

Parámetros por referencia

Se pasan las direcciones de las variables que queremos sean modificadas


por la función. Dentro de la función definimos los punteros que
almacenan las citadas direcciones.

#include
#include<stdio.h>
<stdio.h>
x p1 8A48 void
void intercambio
void intercambio
intercambio (int *,
*,int
(int(int *);
*p1,
int *);int
int*p2)
85 void
void
main
intercambio
(void)
(int *p1, *p2)
{
void{ main (void)
8A48 {{ int
inttmp;
int
intx=5,
x=5,
tmp
tmp;
y=8;
=y=8;
*p1; El contenido de 8 lo
y p2 8A4A tmp = *p1;Son punteros almacenan
58 intercambio
intercambio
*p1
(&x,
==*p2; &y); apuntado por p1
(&x,&y);
8A4A printf*p1
printf (“\n
(“\n
*p2;
x=
x= %d”,
%d”,
direcciones
x);
x);
*p2
*p2 ==tmp;
tmp;
printf (“\n y= %d”,
printf (“\n y= %d”, y); y);
Memoria
tmp 5? }} }}
main Se pasan las direcciones
Memoria 5
intercambio

8
Punteros sin tipo

Punteros sin tipo


‹ ¿Quées un puntero sin tipo?.
Un puntero de tipo void.
void *p;

‹ ¿Para qué sirve un puntero sin tipo?

void *p; p = &a;


int a = 5; P = &b;
double b = 3.4

9
Punteros sin tipo
‹ Antesde usar el valor apuntado
necesitamos forzar el tipo.
void *p;
int a = 5, b;
p = &a;
b = (* (int *)p );
‹ ¿Os imagináis como están hechas
printf y scanf?.

Memoria dinámica

10
Memoria dinámica
‹ Los punteros y la memoria dinámica
están muy relacionados… pero no
siempre van juntos.
‹ Podemos trabajar con punteros sin
memoria dinámica.
‹ ¿Un ejemplo?.

Parámetros por referencia.


Tablas.

Memoria dinámica
‹ ¿Qué es la memoria dinámica?.
‹ Memoria que reservamos durante la
ejecución de nuestro programa.
‹ Ejemplo típico: romper la limitación
de las tablas (listas, pilas, colas,
etc.)

11
Memoria dinámica
‹ Reservar memoria:
#include <stdlib.h>
stdlib.h>
void *malloc(
malloc( size_t size );

‹ ¿Qué devuelve esta función?.


‹ ¿Qué necesita como parámetro?.

‹ Esta palabra reservada nos va a ser


útil: sizeof.

Memoria dinámica
‹ ¿Cómo podemos crear un puntero
al número 5 con memoria
dinámica?.

1. int *p;
2. p = (int *)malloc(sizeof(int));
3. (*p)=5;

12
Memoria dinámica
‹ Importante !!!!!!
Si reservamos memoria hemos de
liberarla.

Nadie lo va a hacer en nuestro lugar.

‹ Si no la liberamos, es un trozo de
memoria que NADIE puede usar.
‹ Si perdemos el puntero al trozo de
memoria, ya no podremos liberarla.

Memoria dinámica
‹ Liberar memoria.
#include <stdlib.h>
void free( void *ptr );

‹ Un ejemplo:
1. int *p;
2. p = (int
(int *)malloc(sizeof(int
*)malloc(sizeof(int));
));
3. (*p)=5;
4. free(p);
free(p);

13
Punteros a estructuras

Punteros a estructuras
Acceso a los campos de una estructura:
struct
structTR TR
{{
T1
T1c1; c1;
T2
T2c2; c2;
...... Son necesarios los paréntesis
Tn
Tncn; cn; porque el operador “.” es de
}};; mayor precedencia que el “*”
struct
structTR TRr,r,*pr;
*pr;

Acceso
Accesoaatravés
travésde
devariable
variableestructura
estructura
r.ci
r.ci
Acceso
Accesoaatravés
travésde
depuntero
punteroaaestructura
estructura
(*pr).ci
(*pr).ci

14
Punteros a estructuras
Acceso a los campos de una estructura:
typedef
typedefstruct
struct
En C (y en C++) {{
existe un operador Cadena
Cadenanombre,
nombre,apellido1,
apellido1,apellido2;
apellido2;
para simplificar el int
intedad;
edad;
long
longdni;
dni;
acceso a los char
charsexo;
sexo;
campos de una }}Tpersona;
Tpersona;
estructura Tpersona
Tpersonaempleado,
empleado,*p;
*p;
referenciada por un
puntero: ‘->’ Acceso
Accesoaatravés
travésde
devariable
variableestructura
estructura
strcpy
strcpy(empleado.nombre,
(empleado.nombre,"Alicia");
"Alicia");
printf
printf("%d",
("%d",empleado.edad);
empleado.edad);
Acceso
Acceso a travésde
a través depuntero
punteroaaestructura
estructura
p->sexo = ‘m’;
p->sexo = ‘m’;
(*p).sexo
(*p).sexo==‘m’;
‘m’;

Punteros a estructuras
¿Cómo creamos nuevas estructuras de
manera dinámica?.
typedef
typedefstruct
struct
{{
Cadena pp==(Tpersona
(Tpersona*)*)malloc(sizeof(Tpersona));
malloc(sizeof(Tpersona));
Cadenanombre,
nombre,apellido1,
apellido1,apellido2;
apellido2;
int edad;
int edad;
long
longdni;
dni; /*/*ppapunta
char apuntaaauna
unaestructura
estructurade
detipo
tipo
charsexo;
sexo; Tpersona
Tpersona cuya memoria ha sidoreservada
cuya memoria ha sido reservada
}}Tpersona;
Tpersona; durante
durantelalaejecución
ejecución*/*/
Tpersona
Tpersona*p;
*p;

15
Punteros a matrices

Punteros a matrices
‹ Una matriz es un puntero constante
a la primera de un conjunto de
posiciones de memoria consecutivas
que guardan datos del mismo tipo

16
Punteros a matrices
¿Cómo recorremos una matriz con un
puntero?

int
int t[]
t[] =
= {1,
{1, 2,
2, 3,
3, 5}; pp =
5}; = &t[0];
&t[0];
int *p;
int *p;
int
int i;i; for
for (i
(i =
= 0;
0; ii <
< 5;
5; i++)
i++) {{
printf("%d
printf("%d ", (*(p+i)) );
", (*(p+i)) );
}}

Memoria dinámica
‹ ¿Cómo podemos crear
dinámicamente una tabla de
enteros de 5 posiciones?.

1. int *p;
2. p = (int
(int *)malloc(sizeof(int
*)malloc(sizeof(int)) *5 );
3. (*p)=5;

¿Qué
significa
esto?

17
‹ Siempre que se llama a malloc hay
que llamar a…

4. free(p);

Punteros a punteros a
punteros a punteros….

18
Punteros a punteros….
‹ Puedo tener punteros que apunten a
punteros.
‹ Y punteros que apunten a punteros
que apunten a punteros.
‹ Y punteros que apunten a punteros
que apunten a punteros que apunten
a punteros.
‹ Y …..

Punteros a punteros….
¿Cómo declaramos un puntero que
apunte a un puntero a entero?.
int **a;
¿Cómo guardamos en a el entero 5
(usando todas las variables auxiliares
necesarias)?
int b = 5, *c;
c = &b;
a = &c;

19
Punteros a punteros….
¿Cómo mostramos el valor de a?.
printf(“%d “, **a);

Un dibujo.

Punteros a punteros….
‹ Un ejemplo: intercambiar dos punteros de
manera que, cuando termine la función, a apunta
a donde apuntaba b y b a donde apuntaba a.
void
voidintercambia(int
intercambia(int*a,
*a,int
int*b); void
*b); voidintercambia(int
intercambia(int*a,
*a,int
int*b)
*b){{
int *tmp;
int *tmp;
int
intmain()
main(){{
int
int*a,
*a,*b; tmp
*b; tmp==a;a;
int
intx=1,
x=1,y=2;
y=2; aa==b;
b;
aa==&x;
&x; bb==tmp;
tmp;
bb==&y;
&y; }}

intercambia(a,
intercambia(a,b);
b);
printf("%d
printf("%d//%d
%d\n",
\n",*a,
*a,*b);
*b);
}} ¿Por qué no funciona?
¿Cómo lo arreglamos?

20
Punteros a funciones

Punteros a funciones
‹ ¿Qué es un puntero a una función?.
‹ ¿Para qué sirve?.

‹ Un ejemplo:
void calcular(int r, void (*avisa)(int)); void m1(int r) {
void m1(int); printf("1: %d\n", r);
void m2(int); }

void main() { void m2(int r) {


calcular(5, m1); printf("2: %d\n", r);
calcular(8, m1); }
}
void calcular(int r, void (*avisa)(int)) {
int t = r+1;
(*avisa)(t);
}

21

También podría gustarte