Actualizado el 17 de Enero del 2019 (Publicado el 11 de Enero del 2019)
1.555 visualizaciones desde el 11 de Enero del 2019
2,3 MB
47 paginas
Creado hace 11a (13/05/2014)
13/05/2014
Fundamentos de la programación
2013‐2014
9
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Facultad de Informática
Luis Hernández Yáñez
Universidad Complutense
Direcciones de memoria y punteros
Operadores de punteros
Punteros y direcciones válidas
Punteros no inicializados
Un valor seguro: NULL
Copia y comparación de punteros
Tipos de punteros
Punteros a estructuras
Punteros a constantes y punteros constantes
Punteros y paso de parámetros
Punteros y arrays
Memoria y datos del programa
Memoria dinámica
Punteros y datos dinámicos
Gestión de la memoria
Inicialización de datos dinámicos
Errores comunes
Arrays de datos dinámicos
Arrays dinámicos
Fundamentos de la programación: Punteros y memoria dinámica
Página 1
1
13/05/2014
Página 2
5
...
...
00000000
00000000
00000000
00000101
Fundamentos de la programación: Punteros y memoria dinámica
Los datos en la memoria
Todo dato (variable o constante) de un programa se almacena
en la memoria: en unos cuantos bytes a partir de una dirección.
int i = 5;
Dirección base
Dirección base
i
0F03:1A37
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
El dato (i) se accede a partir de su dirección base(0F03:1A38),
la dirección de la primera celda de memoria utilizada por ese dato.
El tipo del dato (int) indica cuántas celdas (bytes) utiliza ese dato (4):
(La codificación de los datos puede ser diferente. Y la de las direcciones también.)
00000000 00000000 00000000 00000101 5
0F03:1A3C
Fundamentos de la programación: Punteros y memoria dinámica
Página 3
2
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
13/05/2014
Los punteros contienen direcciones de memoria
Una variable puntero(o simplemente puntero) sirve para acceder
a través de ella a otro dato del programa.
El valor del puntero será la dirección de memoria base de otro dato.
Indirección:
Indirección:
Acceso indirecto a un dato
Acceso indirecto a un dato
punt apuntaa i
punt apuntaa i
0F03:1A39
0F03:1A38
puntpunt
ii
5
¿De qué tipo es el dato apuntado?
¿De qué tipo es el dato apuntado?
¿Cuántas celdas ocupa?
¿Cuántas celdas ocupa?
¿Cómo se interpretan los 0s y 1s?
¿Cómo se interpretan los 0s y 1s?
i
0F03:1A3A
punt
0F03:1A3B
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
00
00
00
05
...
0F
03
1A
38
...
Fundamentos de la programación: Punteros y memoria dinámica
Página 4
Los punteros contienen direcciones de memoria
¿De qué tipo es el dato apuntado?
La variable a la que apunta un puntero, como cualquier otra variable,
será de un tipo concreto (¿cuánto ocupa? ¿cómo se interpreta?).
El tipo de variable a la que apunta un puntero se establece
al declarar la variable puntero:
El puntero nombreapuntará a una variable del tipoindicado
(el tipo base del puntero).
El asterisco (*) indica que es un puntero a datos de ese tipo.
El puntero puntapuntará a una variable entera (int).
int *punt; // punt inicialmente contiene una dirección
// que no es válida (no apunta a nada).
tipo *nombre;
int i; // Dato entero vs. int *punt; // Puntero a entero
Fundamentos de la programación: Punteros y memoria dinámica
Página 5
3
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
13/05/2014
Los punteros contienen direcciones de memoria
// que no es válida (no apunta a nada).
int *punt; // punt inicialmente contiene una dirección
Las variables puntero tampoco se inicializan automáticamente.
Al declararlas sin inicializador contienen direcciones que no son válidas.
Un puntero puede apuntar a cualquier dato del tipo base.
Un puntero no tiene por qué apuntar necesariamente a un dato
(puede no apuntar a nada: valor NULL).
Para implementar el paso de parámetros por referencia.
Para manejar datos dinámicos.
(Datos que se crean y destruyen durante la ejecución.)
¿Para qué sirven los punteros?
Fundamentos de la programación: Punteros y memoria dinámica
Página 6
Fundamentos de la programación: Punteros y memoria dinámica
Página 7
4
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
Obtener la dirección de memoria de ...
int i;
cout << &i; // Muestra la dirección de memoria de i
El operador monario &devuelve la dirección de memoria base
del dato al que se aplica el operador. Operador prefijo (precede).
A un puntero se le puede asignar la dirección base de cualquier dato
del mismo tipo que el tipo base del puntero:
Ahora, el puntero puntya contiene una dirección de memoria válida.
punt apuntaa (contiene la dirección base de) la variable entera i(int).
int i;
int *punt;
punt = &i; // punt contiene la dirección base de i
&&
puntpunt
ii
5
Fundamentos de la programación: Punteros y memoria dinámica
Página 8
Obtener la dirección de memoria de ...
&&
int i, j;
...
int *punt;
i
j
punt
...
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
Fundamentos de la programación: Punteros y memoria dinámica
Página 9
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
13/05/2014
5
&&
&&
Obtener la dirección de memoria de ...
int i, j;
...
int *punt;
...
i = 5;
ii
5
00
00
00
05
i
j
punt
...
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
Fundamentos de la programación: Punteros y memoria dinámica
Página 10
Obtener la dirección de memoria de ...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
puntpunt
ii
5
i
j
punt
...
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
00
00
00
05
0F
03
1A
38
Fundamentos de la programación: Punteros y memoria dinámica
Página 11
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
13/05/2014
6
Obtener lo que hay en la dirección ...
**
El operador monario *accede a lo que hay en la dirección de memoria
a la que se aplica el operador (un puntero). Operador prefijo (precede).
Una vez que un puntero contiene una dirección de memoria válida,
se puede acceder al dato al que apunta con este operador.
*punt: lo que hay en la dirección que contiene el puntero punt.
Como el puntero puntcontiene la dirección de memoria de
la variable i, *puntaccede al contenido de esa variable i.
Acceso indirecto al valor de i.
Se obtienen, a partir de la dirección de memoria base que contiene
punt, tantos bytes como correspondan al tipo base (int) (4) y se
interpretan como un dato de ese tipo base (int).
punt = &i;
cout << *punt; // Muestra lo que hay en la dirección punt
Fundamentos de la programación: Punteros y memoria dinámica
Página 12
Obtener la dirección de memoria de ...
**
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
j = *punt;
punt:
punt:
i
j
punt
...
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
00
00
00
05
0F0F
0F
03
0303
1A
1A1A
3838
38
Fundamentos de la programación: Punteros y memoria dinámica
Página 13
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
13/05/2014
7
Obtener la dirección de memoria de ...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
j = *punt;
Direccionamiento
Direccionamiento
indirecto
indirecto
(indirección).
(indirección).
Se accede al dato i
Se accede al dato i
de forma indirecta.
de forma indirecta.
*punt:
*punt:
i
j
punt
...
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
00
0000
00
0000
00
0000
05
0505
0F
03
1A
38
Fundamentos de la programación: Punteros y memoria dinámica
Página 14
Obtener la dirección de memoria de ...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
j = *punt;
i
j
punt
...
0F03:1A38
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
00
00
00
05
0000
0000
0000
0505
0F
03
1A
38
Fundamentos de la programación: Punteros y memoria dinámica
Página 15
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
**
**
13/05/2014
8
13/05/2014
Ejemplo de uso de punteros
#include <iostream>
using namespace std;
punteros.cpp
int main() {
int i = 5;
int j = 13;
int *punt;
punt = &i;
cout << *punt << endl; // Muestra el valor de i
punt = &j;
cout << *punt << endl; // Ahora muestra el valor de j
int *otro = &i;
cout << *otro + *punt << endl; // i + j
int k = *punt;
cout << k << endl; // Mismo valor que j
return 0;
}
Fundamentos de la programación: Punteros y memoria dinámica
Página 16
Fundamentos de la programación: Punteros y memoria dinámica
Página 17
9
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
13/05/2014
Todo puntero ha de tener una dirección válida
Un puntero sólo debe ser utilizado para acceder al dato al que apunte,
si se está seguro de que contiene una dirección válida.
Un puntero NO contiene una dirección válida tras ser definido.
Un puntero obtiene una dirección válida:
Al copiarle otro puntero (con el mismo tipo base)
que ya contenga una dirección válida.
Al asignarle la dirección de otro dato con el operador &.
Al asignarle el valor NULL(indica que se trata de un puntero nulo,
un puntero que no apunta a nada).
int i;
int *q; // q no tiene aún una dirección válida
int *p = &i; // p toma una dirección válida
q = NULL; // ahora q ya tiene una dirección válida
q = p; // otra dirección válida para q
Fundamentos de la programación: Punteros y memoria dinámica
Página 18
Punteros que apuntan a saber qué...
int *punt; // no inicializado
*punt = 12;
¿Dirección de la zona de datos del pr
Links de descarga
http://lwp-l.com/pdf14815
Comentarios de: 9. Punteros y memoria dinámica - Fundamentos de la programación (0)
Comentarios de: 9. Punteros y memoria dinámica - Fundamentos de la programación (0)
No hay comentarios