Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM....

10
1 Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual [email protected] Memoria Lugar donde almacenan los datos y las instrucciones Compuesta de un gran número de bytes Cada byte puede almacenar un valor representado por 8 cifras binarias (bits) A cada byte se le asigna un número de identificación Dirección de memoria Referencia para acceder a un byte Dirección Contenido 0 00100000 1 00000001 2 10001000 54 00100100 Memoria ¿Qué necesita el compilador para generar el código para acceder a una variable? La dirección de memoria del byte inicial de la variable El número de bytes que componen la variable Memoria ¿De dónde obtiene la dirección inicial? La dirección del byte inicial la obtiene a través del nombre de la variable Sustituirá el nombre por la dirección inicial dentro del programa final ¿Y el número de bytes? El número de bytes viene definido por el tipo de la variable (char - > 1, int -> 4, …) El compilador se encarga de reservar para dicha variable el número de bytes que indique su tipo

Transcript of Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM....

Page 1: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

1

Punteros y Memoria Dinámica I

Curso INEM. Programación en C++ Santiago Muelas Pascual

[email protected]

Memoria

!   Lugar donde almacenan los datos y las instrucciones

!   Compuesta de un gran número de bytes

!   Cada byte puede almacenar un valor representado por 8 cifras binarias (bits)

!   A cada byte se le asigna un número de identificación

!   Dirección de memoria

!   Referencia para acceder a un byte

Dirección Contenido

0 00100000

1 00000001

2 10001000

54 00100100

Memoria

!   ¿Qué necesita el compilador para generar el código para acceder a una variable?

•  La dirección de memoria del byte inicial de la variable

•  El número de bytes que componen la variable

Memoria

!   ¿De dónde obtiene la dirección inicial? !   La dirección del byte inicial la obtiene a través del nombre de la

variable !   Sustituirá el nombre por la dirección inicial dentro del programa final

!   ¿Y el número de bytes? !   El número de bytes viene definido por el tipo de la variable (char -

> 1, int -> 4, …) !   El compilador se encarga de reservar para dicha variable el número de

bytes que indique su tipo

Page 2: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

2

Punteros

!   Nuevo tipo básico de variables

!   También almacenan información pero distinta

!   El resto de los tipos almacenan datos relativos al cálculo del programa

!   Los punteros almacenan direcciones de memoria

!   El tamaño en bytes viene dado por el tamaño de la direcciones que utilice el computador

!   Actualmente 4(32bits) o 8(64 bits)

Punteros

!   Un puntero apunta a un dato

!   Del cual tiene que conocer su tamaño (tipo)

!   Para acceder a memoria hay que conocer lo que ocupa !   ¡Cuando se define una variable hay que especificar su tipo!

Definición

tipo *variable;

Ej int *a;

¡OJO!

Ej int *a,b; !   a es un puntero a un entero, b es un entero���

Operadores

!   Operador de dirección: & !   Para poder obtener la dirección de una variable !   Para poder almacenar la direccion hará falta una

variable puntero con el mismo tipo !   No confundir con el paso por referencia (misma

sintáxis)

!   Operador de indirección: * !   Para de acceder al dato almacenado en una dirección !   Realiza la función opuesta del operador & !   Sólo se debe utilizar con punteros

Page 3: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

3

Ejemplo

Dirección

px-> 35: y -> 39:

Contenido Gráfica

? ? ? ? 0 0 0 3

? px

3 y

px-> 35: y -> 39:

0 0 0 39 0 0 0 3

39

3 y

px

px-> 35: y -> 39:

0 0 0 39 0 0 0 5

39

5 y

px

int main() {

}

int *px,y=3; px=&y;

*px=5;

/* px apunta a y */

/* y vale 5 */

Precendencia ( ) [ ] . -> ++ -- (post)

!sizeof, ++ -- (pre) &(dirección) *(indirección)

* / %

+ -

<< >>

< <= > >=

== !=

&

^

|

&&

||

= += -= *= /= %=

? :

Conversión de punteros

!   Todos los punteros son direcciones de memoria exactamente iguales unas a otras

!   Se puede transferir el contenido de un variable a otra con tipos base distintos

Conversión de punteros

!   No hay conversión automática entre punteros

!   Dos mecanismos !   Casting explícito ���

int* a;���char* b = (char *)a;

! reinterpret_cast (Sólo permite casting entre punteros)

! char* b = reinterpret_cast<char*>(a);

!   ¿Qué sucede con esta conversión?���

Page 4: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

4

Ejercicio

!   Escriba un programa que:

!   Obtenga la dirección de memoria de la variable a (int a=3;)

!   La almacene en una variable ptr de tipo puntero

!   Muestre por pantalla el valor de ptr

!   Establezca en la dirección indicada en ptr el valor 5

!   Imprima el valor de a

13

Punteros a void

!   Punteros cuyo tipo base es void !  (void*)

!   Pueden ser utilizados como punteros genéricos !   Será posible convertir cualquier puntero a void* sin mensaje de error por parte del compilador !   Para tener una colección de punteros heterogéneos

!   Para poder convertir del tipo void * a cualquier otro será necesario utilizar los mecanismos anteriores.

!   Declarar una variable (que no sea un puntero) de tipo void no tiene sentido

Puntero Nulo

!   Uno de los mayores problemas en la programación: punteros definidos sin valor inicial !   ¿Qué contienen?

! Contedrán valores aleatorios

!   Resultados impredecibles

!   Es necesario asignar una dirección que ninguna variable pueda contener esa dirección

!   Para que se detecte un error en el momento en el que se vaya a utilizar

!   Se utiliza la dirección 0

Uso de const con punteros

!   Dos formas: !   Puntero constante a una variable

!   No se puede modificar la dirección pero sí el valor

!   Se tiene que inicializar con un valor

!   Puntero a una variable constante !   Se puede modificar la dirección pero no el valor

Page 5: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

5

Uso de const con punteros int a = 3;

int * const p_a = &a; // Puntero cte a una variable

¿*p_a = 6; ?

¿p_a = NULL;?���

const int a = 3;

cont int *p_a = &a; // Puntero a una variable cte

¿*p_a = 6;?

¿p_a = NULL;?

Uso de const con punteros int a = 3;

int * const p_a = &a; // Puntero cte a una variable

*p_a = 6; // BIEN

p_a = NULL; // ERROR���

const int a = 3;

cont int *p_a = &a; // Puntero a una variable cte

¿*p_a = 6; ?

¿ p_a = NULL; ?

Uso de const con punteros int a = 3;

int * const p_a = &a; // Puntero cte a una variable

*p_a = 6; // BIEN

p_a = NULL; // ERROR���

const int a = 3;

cont int *p_a = &a; // Puntero a una variable cte

*p_a = 6; // ERROR

p_a = NULL; // BIEN

Referencias

!   Concepto parecido al de puntero

!   Una variable de tipo referencia contiene la dirección de otra variable

tipo& nombre_variable = variable_a_la_que_apunta;

!   Como un puntero constante

!   Hay que inicializar la variable con un valor !   No puede cambiar el valor de la variable a la que apunta

!   No puede inicializarse con el valor 0

Page 6: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

6

Referencias

!  Facilita la escritura: !  Para acceder al contenido no hace falta

usar el operador * !  Para asignarle una dirección no hace falta

usar el operador &

Referencias

int a = 5;

int& b = a; // No hace falta poner &a

b = 3; // No hace falta utilizar *, a cambiaría a 3

Ejercicio

!   Cree un programa que defina una variable constante entera y cree las siguientes variables que apunten a la variable entera e impriman su contenido por pantalla: !   Puntero

!   Puntero constante

!   Referencia

!   ¿Referencia constante?

23

Arrays y punteros

!   El identificador de una variable array tiene el valor de la dirección del primer elemento.

!   Por lo tanto, es un puntero y puede usarse como tal

int a[5]={10,20,30,40,50};

int b=*a;

!   El identificador de una variable array es además un puntero constante por lo que no puede ser modificado

10 20 30 40 50

a

b 10

Page 7: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

7

Arrays y punteros

int a[5]={10,20,30,40,50}; 10 20 30 40 50 a

pb

pc

11 20 30 40 50 a

11 20 30 44 50 a

pb pc

int *pb,*pc;

pb=a;

*pb=11;

pc=&a[3];

*pc=44;

Aritmética de Punteros

!   Tratar a los punteros como variables numéricas

!   Se pueden realizar un número limitado de operaciones aritméticas con punteros !   Un puntero puede ser incrementado o decrementado

por un entero (operadores +,+=,++,-,-=,--) !   Para acceder a las posiciones contiguas de la

dirección original !   Un puntero puede ser restado de otro

!   Normalmente suele ser un error si se aplica sobre variables que no sean arrays.

Aritmética de Punteros

!   Si sumamos 3 a un puntero, el resultado será el valor original más 3*(tamaño del tipo en bytes)

!   Si se restan dos punteros de tipo_a, el resultado será el número de elementos de tipo tipo_a que hay entre ambos int a[] = {1,2,3,4};

int a[] = {1,2,3,4};

int *b = a;

¿*(b+2) = 2; ?

¿ int pos = b – a;?

Aritmética de Punteros

!   Si sumamos 3 a un puntero, el resultado será el valor original más 3*(tamaño del tipo en bytes)

!   Si se restan dos punteros de tipo_a, el resultado será el número de elementos de tipo tipo_a que hay entre ambos int a[] = {1,2,3,4};

int a[] = {1,2,3,4};

int *b = a;

*(b+2) = 2; // Equivale a b[2] = 2

int pos = b – a; // pos valdrá 2

Page 8: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

8

Ejercicios

!   Escriba un programa que imprima los elementos del siguiente array

int valores[] = {7,6,5,4};

Utilizando la variable (int *ptr) y modificándola por medio del operador ++

29

Punteros y Clases/Structs

struct Fecha {

int anyo, mes, dia;

;

Fecha a, *ptr;

ptr = &a;

¿Cómo accedemos al atributo anyo por medio de ptr?

Programación en C 30

Punteros y Clases/Structs

struct Fecha {

int anyo, mes, dia;

;

Fecha a, *ptr;

ptr = &a;

(*ptr).anyo = 1970; //dereferenciamos e indexamos

Programación en C 31

Punteros y Clases/Structs

struct Fecha {

int anyo, mes, dia;

;

Fecha a, *ptr;

ptr = &a;

(*ptr).anyo = 1970; //dereferenciamos e indexamos

ptr->anyo = 1970; // o utilizamos el operador flecha (->)

Programación en C 32

Page 9: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

9

Arrays de punteros

!   Un array puede contener punteros

!   El uso más común es para tener almacenados un conjunto de arrays de chars

!   Cada elemento será un puntero al primer carácter de cada array de char

!   Cada array del array puede tener distinto número de elementos !   Con arrays multidimensionales esto no era posible

Arrays de punteros

char* nombres[] = {“Juan”,”Pepe”, “Maria”};

Dirección

nombres[0] 10

nombres[1] 15

nombres[2] 21

Dirección

10 ‘J’ ‘u’ ‘a’ ‘n’ ‘\0’

15 ‘P’ ‘e’ ‘p’ ‘e’ ‘\0’

21 ‘M’ ‘a’ ‘r’ ‘i’ ‘a’ ‘\0’

Ejercicio

!   ¿Qué habría que hacer para conseguir la salida indicada?

35

char* nombres[] = {“Juan”,”Pepe”, “Maria”};

// Que sentencias habria que poner para que

cout << nombres[0] << endl; // Imprima Pepe

cout << nombres[1] << endl; // Imprima Juan

Arrays de punteros

char* nombres[] = {“Juan”,”Pepe”, “Maria”};

char* tmp = nombres[0];

nombres[0] = nombres[1];

nombres[1] = tmp;���

Dirección

nombres[0] 15

nombres[1] 10

nombres[2] 21

Dirección

10 ‘J’ ‘u’ ‘a’ ‘n’ ‘\0’

15 ‘P’ ‘e’ ‘p’ ‘e’ ‘\0’

21 ‘M’ ‘a’ ‘r’ ‘i’ ‘a’ ‘\0’

Page 10: Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual smuelas@fi.upm.es Memoria!! Lugar donde

10

Ejercicios

37