Download - Punteros y Memoria Dirección Contenido Dinámica I · Punteros y Memoria Dinámica I Curso INEM. Programación en C++ Santiago Muelas Pascual [email protected] Memoria!! Lugar donde

Transcript
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