Actualizado el 15 de Junio del 2021 (Publicado el 6 de Diciembre del 2018)
1.217 visualizaciones desde el 6 de Diciembre del 2018
3,0 MB
46 paginas
Creado hace 11a (04/09/2013)
Fundamentos de la programación
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 puntero
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
Errores comunes
Arrays de datos dinámicos
Arrays dinámicos
z
e
ñ
á
Y
z
e
d
n
á
n
r
e
H
s
i
u
L
Fundamentos de la programación: Punteros y memoria dinámica
849
854
864
866
867
868
873
875
877
879
883
886
891
895
907
911
916
928
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
Fundamentos de la programación: Punteros y memoria dinámica
Página 849
Los datos en la memoria
...
i
int i = 5;
Todo dato se almacena en memoria:
Varios bytes a partir de una dirección
Dirección base
Dirección base
El dato (i) se accede a partir de su dirección base(0F03:1A38)
Dirección de la primera celda de memoria utilizada por el dato
El tipo del dato (int) indica cuántos bytes (4) requiere el dato:
(La codificación de los datos puede ser diferente; y la de las direcciones también)
00000000 00000000 00000000 00000101 5
00000000
00000000
00000000
00000101
0F03:1A39
0F03:1A3A
0F03:1A3B
0F03:1A37
0F03:1A38
0F03:1A3C
...
Fundamentos de la programación: Punteros y memoria dinámica
Página 850
Los punteros contienen direcciones de memoria
Un punterosirve para acceder a través de él a otro dato
El valor del puntero es 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
i
0F03:1A3A
punt
0F03:1A3B
0F07:0417
0F07:0418
0F07:0419
0F07:041A
...
00
00
00
05
...
0F
03
1A
38
...
ii
5
¿Cuántas celdas ocupa?
¿Cuántas celdas ocupa?
¿Cómo se interpretan los 0/1?
¿Cómo se interpretan los 0/1?
¿De qué tipo es el dato apuntado?
¿De qué tipo es el dato apuntado?
Fundamentos de la programación: Punteros y memoria dinámica
Página 851
Los punteros contienen direcciones de memoria
¿De qué tipo es el dato apuntado?
La variable a la que apunta un puntero será de un tipo concreto
¿Cuánto ocupa? ¿Cómo se interpreta?
El tipo de variable apuntado se establece al declarar el puntero:
El puntero nombreapuntará a una variable del tipoindicado
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 852
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
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 no válidas
Un puntero puede apuntar a cualquier dato de su 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 implementar los arrays
¿Para qué sirven los punteros?
Fundamentos de la programación: Punteros y memoria dinámica
Página 853
Fundamentos de la programación: Punteros y memoria dinámica
Página 854
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
Operador monario y prefijo
&devuelve la dirección de memoria base del dato al que precede
Un puntero puede recibir la dirección de datos de su tipo base
Ahora puntya contiene una dirección de memoria válida
punt apuntaa (contiene la dirección de) la variable i(int)
int i;
int *punt;
punt = &i; // punt contiene la dirección de i
puntpunt
ii
Fundamentos de la programación: Punteros y memoria dinámica
Página 855
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 856
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, 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 857
Obtener la dirección de memoria de ...
int i, j;
...
int *punt;
...
i = 5;
punt = &i;
i
j
puntpunt
punt
ii
5
...
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 858
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 lo que hay en la dirección ...
**
Operador monario y prefijo
*accede a lo que hay en la dirección de memoria a la que precede
Permite acceder a un dato a través un puntero que lo apunte:
*punt: lo que hay en la dirección que contiene el puntero punt
puntcontiene la dirección de memoria de la variable i
*puntaccede al contenido de esa variable i
Acceso indirecto al valor de i
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 859
Obtener lo que hay en la dirección ...
**
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
0303
03
1A1A
1A
3838
38
Fundamentos de la programación: Punteros y memoria dinámica
Página 860
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 lo que hay en la dirección ...
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
...
0000
00
0000
00
0000
00
0505
05
0F
03
1A
38
Fundamentos de la programación: Punteros y memoria dinámica
Página 861
Obtener lo que hay en la dirección ...
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 862
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
punteros.cpp
punteros.cpp
Ejemplo de uso de punteros
#include <iostream>
using namespace std;
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 863
Fundamentos de la programación: Punteros y memoria dinámica
Página 864
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
Todo puntero ha de tener una dirección válida
Un puntero sólo debe ser utilizado si tiene 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:
Asignando la dirección de otro dato (operador &)
Asignando otro puntero (mismo tipo base) que ya sea válido
Asignando el valor NULL(puntero nulo, 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 = p; // ahora q ya tiene una dirección válida
q = NULL; // otra dirección válida para q
Fundamentos de la programación: Punteros y memoria dinámica
Página 865
Punteros que apuntan a saber qué...
int *punt; // No inicializado
*punt = 12; // ¿A qué dato se está asignando el valor?
¿Dirección de la zona de datos del programa?
Un puntero no inicializado contiene una dirección desconocida
¡Podemos modificar inadvertidamente un dato del programa!
¡Podemos modificar el código del propio programa!
¡Podemos modificar el código del propio S.O.!
Consecuencias imprevisibles (cuelgue)
(Los S.O. modernos protegen bien la memoria)
¿Dirección de la zona de código del programa?
¿Dirección de la zona de código del sistema operativo?
Fundamentos de la programación: Punteros y memoria dinámica
Página 866
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
Punteros que no apuntan a nada
int *punt = NULL;
...
*punt = 13;
Inicializando los punteros a NULLpodemos detectar errores:
puntha sido inicializado a NULL: ¡No apunta a nada!
Si no apunta a nada, ¿¿¿qué significa *punt??? No tiene sentido
ERROR: ¡Acceso a un dato a través de un puntero nulo!
Error de ejecución, lo que ciertamente no es bueno
Pero s
Comentarios de: 9. Punteros y memoria dinámica (0)
No hay comentarios