tema 8 punteros

51
Fundamentos de Informática Tema 8 Punteros

Upload: william-vargas-moreno

Post on 12-Apr-2016

40 views

Category:

Documents


1 download

DESCRIPTION

tem punteros

TRANSCRIPT

Page 1: Tema 8 Punteros

Fundamentos de Informática

Tema 8Punteros

Page 2: Tema 8 Punteros

2Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• ¿Qué es un puntero?• Declaración de punteros• Operadores unarios: & y *• Operaciones con punteros

Aritmética de punteros• Punteros y funciones• Punteros y vectores• Asignación dinámica de memoria• Errores típicos al trabajar con punteros

Contenidos

Page 3: Tema 8 Punteros

3Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

¿Qué es un puntero?

1

Page 4: Tema 8 Punteros

4Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

¿Qué es un puntero?

• Es un tipo de variable especial, ya que en lugar de almacenar valores (como una variable de  tipo “int” o “double”)  los punteros almacenan direcciones de memoria.

• La memoria  de  un  ordenador  se  compone  de  una  pila  de  posiciones  de almacenamiento.

Cada  posición  de  almacenamiento  tiene  asignada  una  dirección diferente de memoria.Cada posición de memoria almacena 1 byte.

• Hasta  ahora  hemos  visto  que  cuando  hacemos  referencia  a  una  de  esas direcciones  de  memoria  (mediante  el  uso  de  una  variable),  obtenemos directamente el valor contenido en dicha posición de memoria.

• Mediante  una  variable  de  tipo  puntero,  se  puede  manipular  tanto direcciones de memoria como valores.

Page 5: Tema 8 Punteros

5Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

¿Qué es un puntero?

• Definición:Un  puntero  es  una  variable  con  la  peculiaridad  que  el  dato  que almacena es una dirección de memoria.Un puntero es una variable que “apunta” a otro lugar de memoria.

‘A’123

‘G’10034

33

100001000110005100091000A

34.22‘F’

1003410038

• Son parte esencial de C. • Sus ventajas:

Permiten definir vectores y matrices de tamaño variable, que utilizan sólo la cantidad de memoria necesaria y cuyo tamaño puede reajustarse dinámicamente.Permiten definir estructuras de datos más complejas, como listas o árboles.Mediante los punteros es posible que las funciones devuelvan más de un valor

Page 6: Tema 8 Punteros

6Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Declaración de punteros

2

Page 7: Tema 8 Punteros

7Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Declaración de punteros en C

• Los punteros se declaran igual que las variables normales, pero con un asterisco (*) delante del nombre de las variables:

tipo *pnombre_puntero;• Donde TIPO hace referencia al tipo de datos al que “apuntará” nuestro 

puntero.Es muy importante respetar el tipo de datos al que apunta un puntero. Al igual que en el caso de las variables simples, un descuido en el tipo de datos generará errores.

• Se recomienda, para el nombre de la variable de tipo puntero, poner una ‘p’ que nos “recuerde” que se trata de un puntero.

• Después de su declaración, una variable de tipo puntero contiene un valor inicial cualquiera (como ocurre con cualquier tipo de variables), que apuntará a una dirección aleatoria que puede incluso no existir.

• Ejemplos:char *punt;   /* Variable punt que es de tipo puntero a carácter */int *pcontar; /* Variable pcontar que es de tipo puntero a entero */

Page 8: Tema 8 Punteros

8Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Declaración de punteros en CEjemplos:    double *puntd;

int *punti;

Tanto “puntd” como “punti” son variables de tipo puntero (o punteros para abreviar) y almacenan direcciones de memoria (por lo tanto, ambas ocupan la misma cantidad de memoria). La diferencia es que el dato almacenado en la dirección de memoria contenida en el puntero punti es un entero, mientras que el dato almacenado en la dirección de memoria contenida en el puntero puntd es un double.Se dice que punti “apunta” a un entero y puntd “apunta” a un double.

?

Dirección Valor Variable

?

C2B8

C37A

punti

puntd

C2B8

Dirección Valor Variable

C37A

123

7.4e‐3

Page 9: Tema 8 Punteros

9Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operadores de punteros: & y *

3

Page 10: Tema 8 Punteros

10Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operadores de puntero• Operador &:

Operador unario de dirección.Opera sobre cualquier tipo de variable.Obtiene la dirección de memoria de su operando, es decir, la dirección de memoria de la variable sobre la que se aplica.El compilador dará un aviso si se intenta realizar una asignación en la que no corresponden los tipos.

• Ejemplo:int numero;int *punt;double *punt_d;…numero = 10;punt = № 

/*asignar la dirección de numero a una variable puntero*/punt_d = № /* Aviso, no se corresponden los tipos */ …

Resultado: la variable numero esta en la posición (dirección ) 34FF, después de la asignación a la variable puntero punt tendrá el valor 34FF.

?

Dirección Valor Variable

34FF

34FF

10

punt

numero

Page 11: Tema 8 Punteros

11Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operadores de puntero

• Operador  &:

Lo hemos estado utilizando con la función scanf(), ya que esta función necesita conocer la dirección de la variable donde almacenar el valor leído del buffer de teclado.

int n;printf(“Introduzca el valor de n”);scanf(“%d”, &n);

Page 12: Tema 8 Punteros

12Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operadores de puntero

• Operador  * :Operador unario de indirecciónComplemento del operador &.Permite operar sobre las variables a las que apunta la variable de tipo puntero. Proporciona el valor de la dirección de memoria a la que apunta el puntero sobre el que se aplica, es decir, permite acceder al valor por medio del puntero.

Page 13: Tema 8 Punteros

13Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operadores de puntero• Ejemplo:

...int var1, var2;int *p;var1 = 5;p = &var1;var2 = *p;*p = 10;…

Resultado: pondrá en var2 el valor de var1, por tanto var2 = 5;

ATENCIÓN: Después de la asignación p = &var1; tenemos dos maneras de manipular los valores enteros almacenados en la variable var1: directamente mediante var1 o indirectamente mediante el puntero p.

?

Dirección Valor Variable

34FF

34FF

5   10

p

var1

5 var2

X

Page 14: Tema 8 Punteros

14Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Ejemplo#include <stdio.h>int main(void){

int var1;int *p;

var1 = 12;printf("\nEl valor del dato =%d \n direccion del dato =%x \n",

var1,&var1);p = &var1;printf("\nContenido del puntero=%x \n Direccion del puntero= %x",

p,&p);printf("\n valor referenciado por puntero = %d", *p);return 0;

}Resultado: el valor del dato = 12

direccion del dato = 20a2el contenido del puntero= 20a2direccion del puntero= 129fvalor referenciado por puntero = 12

Page 15: Tema 8 Punteros

15Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punteros

4

Page 16: Tema 8 Punteros

16Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punteros• Asignación de punteros:

Es posible asignar una dirección de una variable a un puntero (ej1)Es posible asignar el contenido de un puntero a otro puntero (ej2)

#include <stdio.h>int main(void){

int a;int *punt1;int *punt2; a = 10;punt1 = &a; /* ej1 */punt2 = punt1; /* ej2 */printf(" El valor %d esta en la posicion %x ", *punt2, punt2);return 0;

}

Resultado: El valor 10 se encuentra en la posicion 203c .

Page 17: Tema 8 Punteros

17Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punteros• Aritmética de punteros:

Se trata de sumar y restar, incrementar o decrementar variables de tipo punteroDebe entenderse como cambios en la dirección a la que apunta el puntero (se produce un cambio en la dirección de memoria contenida en el puntero).El incremento o decremento de un puntero depende exclusivamente del tipo de dato base dado en la declaración del puntero.Al declarar un puntero es necesario indicar a qué tipo de dato apunta para que cuando se utilicen los incrementos o decrementos se conozca cuánto hay que sumar o restar.La operación de sumar 1 a un puntero hace que su dirección se incremente la cantidad necesaria para pasar a apuntar al siguiente dato del mismo tipo (cantidad que coincide con el número de bytes que ocupa dicho tipo de dato).Por lo tanto, sólo en el caso de variables que ocupan 1 byte en memoria (variables de tipo “char”) la operación de incremento aumenta en 1 la dirección de memoria; en los demás casos aumenta más.

Page 18: Tema 8 Punteros

18Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punteros• Aritmética de punteros:

Sustracción de punteros: • Sólo tiene sentido si apuntan a direcciones diferentes de un mismo VECTOR.

• El resultado de la sustracción es la diferencia de posiciones del VECTOR que existe entre ambos

Es posible comparar punteros mediante cualquier operador de comparación y relacional, pero:• Es necesario que ambos punteros sean del mismo tipo.• Resultan de gran utilidad cuando se trabaja con vectores utilizando punteros.

OPERACIONES PROHIBIDAS CON PUNTEROS• SUMAR PUNTEROS• MULTIPLICAR PUNTEROS• DIVIDIR PUNTEROS

Page 19: Tema 8 Punteros

19Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punteros

• Ejemplo aritmética de punteros: incremento de un puntero#include <stdio.h> int main( void){

int var=7;int *punt1; punt1 = &var;printf("\nLa direccion del dato =%x",&var);printf("\nEl valor que apunta el puntero = %d", *punt1);printf("\nEl contenido de punt1 =%x",punt1);punt1++;printf("\nel contenido de punt1 =%x",punt1);printf("\nEl valor que apunta el puntero = %d",*punt1);return 0;

}

Resultado:La direccion del dato = 1000El valor que apunta el puntero = 7El contenido de punt1 = 1000El contenido de punt1 = 1004El valor que apunta el puntero = ?

Page 20: Tema 8 Punteros

20Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

El incremento o decremento de un puntero depende exclusivamente del tipo de dato base en la declaración del puntero.

• Ejemplo de aritmética de punteros: incremento de un puntero…int *p_int;Si el contenido de p (la dirección de una variable) = 1000, podemos escribir:

p_int 1000p_int +1 1004p_int +2 1008p_int +3 100C… …

char *p_ch;Si el contenido de p(la dirección de una variable) = 1000, podemos escribir:

p_ch 1000p_ch +1 1001p_ch +2 1002

Operaciones con punteros

Page 21: Tema 8 Punteros

21Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

No confundir incremento o decremento del puntero con el incremento o decremento del valor a donde apunta el puntero

• Ejemplo de aritmética de punteros: incremento de un punteroint *p_int;int numero;...numero = 78;    p_int = &numero;*p_int += 8;    p_int += 8;...

Operaciones con punteros

?

Dirección Valor Variable

34E0

34E0

78

p_int

numero

1

?

Dirección Valor Variable

34E0

34E0

86

p_int

numero

Después de *p_int += 82 ?

Dirección Valor Variable

34E0

3500

86

p_int

numero

Después de p_int += 8

???3500

3

123

Page 22: Tema 8 Punteros

22Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punterosSustracción de punteros: sólo tienen sentido si apuntan a direcciones diferentes de un mismo vector

Ejemplo de aritmética de punteros: sustracción de punteros

#include <stdio.h>int main(void){

int vector[5] = {2,4,6,8,10};int *p1, *p2;p1= &vector[0]; p2 = &vector[4];printf("\ndirección del primer elemento =%x ",p1);printf("\ndirección del ultimo elemento =%x ",p2);printf("\n p2-p1 = %d",p2-p1);printf("\n *p2-*p1 = %d",*p2-*p1);return 0;

}

Resultado:dirección del primer elemento = 8276dirección del ultimo elemento = 8286p2 ‐ p1 = 4 (8286‐8276) / 4 = 4

*p2 ‐ *p1 = 8

Page 23: Tema 8 Punteros

23Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Es posible comparar punteros mediante cualquier operador de comparacióny relacional.

Es necesario que ambos punteros sean del mismo tipo.Resultan de gran utilidad cuando trabajamos con vectores utilizando punteros.

• Ejemplo de aritmética de punteros: comparación de punteros

#include <stdio.h>int main(void){ int vector[5] = {2,4,6,8,10};

int *p1, *p2;p1= &vector[0]; p2= &vector[4];if (p1 > p2) {

printf(“\np1 apunta a una dirección más alta que p2”);}else {

if (p1 == p2) {printf(“\np1 y p2 apuntan al mismo elemento del vector”);printf(“\n Y es el elemento %d”, *p1);

}}return 0;

}

Operaciones con punteros

Page 24: Tema 8 Punteros

24Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Ejemplo:

char *pti; double *ptd;.../*Sumamos 1 a un puntero a char*/

pti++;

/*Sumamos 1 a unpuntero a double*/

ptd++;

En cada dirección de memoria se guarda 1 byte.

Si el tipo del puntero ocupa mtipo del puntero ocupa máás de 1 s de 1 bytebyte al incrementar el puntero se adelantan tantas posiciones de memoria como nº de bytes ocupe el tipo de puntero.

Operaciones con punteros

Page 25: Tema 8 Punteros

25Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Operaciones con punteros: Resumen básico• Asignar la dirección de una variable ordinaria a un puntero

p = &variable;• Asignar el valor de un puntero a otro

punt1 = punt2;• Se puede asignar un valor inicial nulo (cero) a un puntero

puntero = NULL;• Se puede sumar o restar un valor entero a un puntero

punt+2, o ‐‐punt.• Tiene sentido restar un puntero a otro si ambos apuntan a los elementos de 

un mismo vector.• Se puede comparar los punteros cuando apunten al mismo tipo de dato.

• PROHIBIDO:Sumar punterosDividir punterosMultiplicar punteros

Page 26: Tema 8 Punteros

26Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Los punteros permiten realizar un paso por referencia de parámetros a funciones:

Es posible cambiar el valor de una variable en el interior de una función y conservar su valor una vez terminada la ejecución de la función.

• Idea:En lugar de pasar la variable como parámetro real a la función (paso por valor) se pasa un puntero a la dirección en la que se encuentra la variable (parámetro por referencia).En el paso por valor, lo único que ocurre es que se hace una copia del valor del parámetro real sobre el parámetro formal, de manera que cualquier cambio en el parámetro formal NO afecta al parámetro real.En el paso por referencia, lo que en realidad se pasa es la dirección de la variable, de manera que los cambios, por tanto, se pueden hacer manipulando el puntero de manera que afecten directamente al contenido de la variable apuntada.

Punteros y funciones

Page 27: Tema 8 Punteros

27Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Ejemplo paso por referencia:

#include <stdio.h>void cambiar (int *x, int *y);int main(void){

int a, b;a = 3;b= 5;printf(“ \nAntes de intercambiar: a = %d, y b = %d”,a,b);cambiar(&a, &b); /* Se pasa la dirección de las dos variables */printf(“\nDespués de intercambio: a = %d, y b = %d”,a,b);return 0;

}void cambiar(int *x, int *y){

int aux;aux = *x; /* A través del puntero x, puedo acceder al valor original */*x = *y;*y = aux;

}

Punteros y funciones

Resultado: Antes de intercambiar: a = 3, y b = 5Después de intercambio: a = 5, y b = 3

Page 28: Tema 8 Punteros

28Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Ejemplo paso por valor: Se hace una copia de las variables y por tanto, NO SE INTERCAMBIAN. NO FUNCIONA CORRECTAMENTE.

#include <stdio.h>void cambiar(int x, int y);int main(void){

int a, b;a = 3;b= 5;printf(“ \nAntes de intercambiar: a = %d, y b = %d”,a,b);cambiar(a, b);printf(“\nDespués de intercambio: a = %d, y b = %d”,a,b);return 0;

}void cambiar(int x, int y){

int aux;aux = x;

x = y;y = aux;

}

Punteros y funciones

Resultado: Antes de intercambiar: a = 3, y b = 5Después de intercambio: a = 3, y b = 5

Page 29: Tema 8 Punteros

29Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

#include <stdio.h>void cambio (int a, int *b);int main(void){

int a, b;a = 2;b = 2;printf(“\nValores antes de hacer la llamada: a = %d, y b =

%d”,a,b);cambio(a,&b);printf(“\nValores después de hacer la llamada: a = %d, y b =

%d”,a,b);return 0;

}void cambio(int a, int *b){

a = 5 * a;*b = 5 * (*b);

}

Resultado: Valores antes de hacer la llamada: a = 2, y b = 2Valores después de hacer la llamada: a = 2, y b = 10

Punteros y funciones

Page 30: Tema 8 Punteros

30Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Punteros y vectores• Una de las aplicaciones más frecuentes de los punteros es el manejo de vectores 

y cadenas de caracteres.

• Como todos los elementos de un vector se almacenan en posiciones consecutivas de memoria, basta conocer la posición de memoria del primer elemento para poder recorrer todo el vector con un puntero.

Page 31: Tema 8 Punteros

31Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Punteros y vectores

#include <stdio.h>

#define N 10

Int main (void)

{ double a[N];

int i;

double *pd;

/* Inicialización */

for (i = 0; i < N; i++){

a[i] = 7.8 *i;

}

/* Imprimir valores */

pd = &a[0];

for (i= 0;i < N; i++) {

printf(“%f\n”, *pd);

pd++;

}

return 0;

}

pa = &a[0];pb = &b[N-1];for (i= 0;i < N; i++) {

*pb = *pa;pa++;pb- -;

}Apunta al 1er elemdel vector

(*pd) es de tipo double

pd pasa a puntar al siguiente elem de a

pa apunta al 1er elem del vector a pb apunta al

último elemdel vector b

Copio un elem

Avanzo un elem de aRetrocedo un

elem de b

Copia de manera inversaInicialización de vector a[] y muestra

su contenido mediante un puntero

pa = &a[0]; pa = a;

EQUIVALENTE

a[3]=27; *(a+3) = 27;

Page 32: Tema 8 Punteros

32Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Punteros y vectores• Ejemplo anterior de la copia inversa completo:

Copiar el vector a en el vector b de manera que sea su inverso.Si a vale [1, 2, 3, 4], después del programa b vale [4, 3, 2, 1]

#include <stdio.h>#define N 4int main(void){ int a[N] = {1,2,3,4}; /* Vector */

int b[N];int *pa;int *pb;.... /* Suponemos que se han inicializado a y b co*/

/* Copia de manera inversa */pa = &a[0]; /* pa apunta al primer elemento del vector a */pb = &b[N-1]; /* pb apunta al último elemento del vector b */for (i= 0;i < N; i++) {

*pb = *pa; /* Copio un elemento */pa++; /* Avanzo un elemento */pb- -; /* Retrocedo un elemento */

}return 0;

}/* Nota: el algoritmo es el mismo independientemente del tipo de datos que esté copiando */

Page 33: Tema 8 Punteros

33Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Punteros y vectores• Equivalencia de punteros y vectores

Cuando se define un vector: double a[N];lo que ocurre es que se reserva espacio en memoria para almacenar N elementos del tipo double y se crea un puntero constante llamado a que apunta al principio del bloque de memoria reservada. Puntero constante: el programa no puede cambiar la dirección almacenada en él.Por lo tanto, para hacer que el puntero pd apunte al principio del vector a se puede hacer de cualquiera de las dos maneras:(a) pd = &a[0];(b) pd = a;El operador [ ]Cuando se accede a un elemento de un vector con 

a[3] = 2.7;el programa toma el puntero constante a, le suma el valor que hay escrito entre los corchetes (según el tamaño de cada tipo de dato), y escribe en dicha dirección el valor 2.7. Por tanto, es equivalente a:

*(a+3) = 2.7;

Page 34: Tema 8 Punteros

34Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Punteros y vectores• Equivalencia de punteros y vectores

Ejemplo: Se tiene un vector (vec) de 100 elementos y se quiere asignar el valor 45 al 5º elemento. Se puede realizar de varias maneras.(a) vec[4] = 45;(b) punt = vec;

punt+=4; /* Mover el puntero hasta la posición 5 */*punt=45; /* Asignarle ese valor */punt ‐= 4; /* Devolver el punt al principio del vector vec */

(c) punt = vec;*(punt+4) = 45;  /* Se calcula la dirección directamente y se asigna*/

(d) punt = vec;punt[4] = 45;

(e)  *(vec + 4) = 45;

Page 35: Tema 8 Punteros

35Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Paso de VECTORES a funciones:El nombre de un vector contiene la dirección del primer elemento del vector.Eso explica el por qué no utilizar el & en el parámetro real al realizar una llamada a una función.El parámetro formal puede especificarse con dos notaciones:• (Opción 1) El vector con tamaño no especificado (int m[ ])• (Opción 2) Un puntero al primer elemento del vector (int *m)

CUESTION DE GUSTOS!!!!!!No olvidar que en un vector:int vector[5];• El valor del primer elemento = ( vector[0] )• La dirección del primer elemento =  ( &vector[0] ) ó con el nombre del vector ( vector )

• En general, la dirección del elemento (i+1) es &vector[i] ó (vector+i)Cuando se indica (vector+1) hay que tener en cuenta que el desplazamiento del puntero depende del tipo base

• El contenido del elemento (i+1): vector[i ] ó *(vector+i)

Punteros y vectores: paso de vectores a funciones

Page 36: Tema 8 Punteros

36Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

#include <stdio.h>#define N 5void escribir (int m[ ]); /* Opción 1 */void escribir (int *m); /* Opción 2 */ int main(void ){

int mat[N]int i;for(i = 0; i<N ; ++i) {

mat[i] = i;}escribir(mat);return 0;

}void escribir(int m[] ) ó void escribir (int *m) /* Según la

opción */{

int cont;for( cont = 0; cont<N; cont++){

printf(“%d ”, m[cont]);}

}

Punteros y funciones

Resultado: 0 1 2 3 4

Page 37: Tema 8 Punteros

37Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

#include <stdio.h>#include <ctype.h>void num_vocales (char *cadena, int *v);int main( void){

char cadena[80];int vocales;printf(“\nIntroduzca una linea de texto:”);gets(cadena);num_vocales(cadena,&vocales);printf(“\nEl nº de vocales: %d”,vocales);return 0;

}void num_vocales(char *cadena, int *v){

char c;int cont = 0;*v = 0;while ( cadena[cont] != ‘\0’) {

c = toupper(cadena[cont]));if (c == ‘A’ || c ==’E’ || c == ‘I’ || c ==’O’ || c

==’U’) (*v)++;

cont++;}

}

Punteros y funciones

Page 38: Tema 8 Punteros

38Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

#include <stdio.h>#define N 5int main(void){

int v[N];int i;for(i= 0;i<N; i++) {

printf("elemento %d=",i+1);scanf("%d",&v[i]);

}for(i = 0; i<N; ++i) {

printf("elemento %d =%d, direccion =%x",i+1,*(v +i),(v+ i));printf("\n");

}return 0;

}

Punteros y funciones

Resultado: Si introducimos 2,4,6,8, y 10 elemento 1 = 2 , dirección = 21baelemento 2 = 4 , dirección = 21beelemento 3 = 6 , dirección = 21c2elemento 4 = 8 , dirección = 21c6elemento 5 = 10 , dirección = 21ca

Page 39: Tema 8 Punteros

39Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Se utiliza esta técnica cuando no se conoce hasta el momento de la ejecución la cantidad de memoria necesaria para almacenar datos.

• Por lo tanto, la asignación dinámica de memoria consiste en que, una vez que se está ejecutando el programa y se conoce la cantidad de memoria que se necesita, se realiza una llamada al sistema operativo para solicitarle un bloque de memoria libre del tamaño adecuado.

• Si queda memoria, el sistema operativo devuelve un puntero que apunta al comienzo de dicho bloque.

• Este puntero permite acceder a la memoria asignada tal y como se desee, siempre y cuando, no se salga de los límites del bloque.

• Una vez que se termina de usar la memoria, ésta debe liberarse al sistema operativo.

Asignación dinámica de memoria

Page 40: Tema 8 Punteros

40Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Funciones para trabajar con asignación dinámica de memoria:Solicitar al sistema operativo un bloque de memoria: calloc() y malloc()Liberar la memoria asignada dinámicamente: free()Están en el archivo de cabecera “stdlib.h” en la librería estándar 

• Solicitar memoria: void *calloc (size_t numero_elementos, size_t tamaño_elemento);void *malloc(size_t tamaño_bloque);

Ambas funciones solicitan al sistema operativo un bloque de memoria de un tamaño dado.Ambas funciones devuelven un puntero al principio del bloque solicitado o NULL si no hay suficiente memoria.ES MUY IMPORTANTE VERIFICAR SIEMPRE que se solicite memoria al sistema operativo que éste nos devuelve un puntero válido Y NO NULL para indicarnos que no tiene memoria disponible.

Asignación dinámica de memoria

Page 41: Tema 8 Punteros

41Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Solicitar memoria: void *calloc (size_t numero_elementos, size_t tamaño_elemento);

La función calloc() reserva un bloque de memoria para un numero_elementos de tamaño_elementoInicializa con ceros el bloque de memoriaDevuelve el puntero genérico (void *) que apunta al principio del bloque o NULL en caso de que no exista suficiente memoria libre ó el número de elementos sea un valor negativo. Para un número de elementos 0, no devuelve NULL.

Ejemplo: Crea un vector de n enterosint *punt;int n;... /* Petición del valor n con la función scanf() */punt = (int *) calloc (n, sizeof(int));if (punt == NULL) {

printf(“Error: No hay suficiente memoria “);}else {

…/* Si hay memoria el programa continuaría y podría usar el vector recién creado */punt[0] =23;

}…

Asignación dinámica de memoria

Page 42: Tema 8 Punteros

42Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Solicitar memoria: void *malloc (size_t tamaño_bloque);

La función malloc() reserva un bloque de memoria de tamaño tamaño_bloque (medido en bytes)Devuelve el puntero genérico (void *) que apunta al principio del bloque o NULL en caso de que no exista suficiente memoria libre.En este caso NO se inicializa el bloque con 0.

Ejemplo: Crea un vector de n enteros, 

int *punt;int n;... /* Petición del valor n con la función scanf() */punt = (int *) malloc (n * sizeof(int));if (punt == NULL) {

printf(“Error: No hay suficiente memoria “);}else {

…/* Si hay memoria el programa continuaría y podría usar el vector recién creado */punt[0] =23;

}…

Asignación dinámica de memoria

Page 43: Tema 8 Punteros

43Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Solicitar memoria: Ambas funciones devuelven un puntero genérico (void *)Este puntero genérico ha de convertirse mediante una conversión de tipos (“cast”) al tipo de dato que se va a introducir en el bloque.En ambas funciones se utiliza el operador sizeof(int) para  especificar la cantidad de memoria que se necesita, lo que es muy importante de cara a la portabilidad del programa. Existe otra función para reasignar memoria cuando se comprueba que con la memoria que se había reservado de manera dinámica no es suficiente. Esta función se llama realloc() pero NO  la se va a utilizar en este curso.

Asignación dinámica de memoria

Page 44: Tema 8 Punteros

44Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Liberar memoria:void free (void *puntero_al_bloque); 

Una vez que se ha terminado de usar la memoria es necesario liberarla para que quede disponible para los demás programas.Esta función libera la memoria previamente asignadamediante las funciones calloc() o malloc().La función libera el bloque a cuyo principio apunta el puntero_al_bloque.Es importante que el puntero_al_bloque apunte exactamente al principio del bloque (debe ser el puntero devuelto por calloc() o malloc()).

Ejemplo: Liberar la memoria previamente asignadaint *punt;int n;... /* Petición del valor n con la función scanf() */punt = (int *) calloc (n, sizeof(int));/* Comprobación */.../* Liberar memoria solo en el caso de asignación correcta*/free(punt);

Asignación dinámica de memoria

Page 45: Tema 8 Punteros

45Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Utilizar un puntero antes de que se le haya asignado memoria.int *punt;*punt = 3;

• Acceder a una posición de memoria que no nos perteneceint *punt;int mat[N];mat[N] = 34; /* Error, el último elemento del vector es el N-1 */

punt = (int *) calloc (N , sizeof(int));if (punt == NULL) .....else{

*(punt+N) = 34, /* Error, la última posición donde apunta punt es N-1 */

}• Solicitar memoria y no comprobar si se ha realizado correctamente la asignación

double *punt;punt = (double *) calloc (n, sizeof(double));punt[0] = 12.76;

/* Error si ocurre que el puntero devuelto por calloc es NULL */

Errores típicos al utilizar punteros

Page 46: Tema 8 Punteros

46Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

• Liberar memoria sin tener el puntero apuntando al principio del bloqueint *punt;punt = (int *) calloc (n, sizeof(int));if (punt == NULL){

....}else {

punt ++; /* se modifica el puntero original */free(punt); /* El programa aborta pues punt no apunta al principio 

del bloque */ }

• Seguir usando la memoria una vez liberadaint *punt;punt = (int *) calloc (n, sizeof(int));if (punt == NULL)

....free(punt); a = punt[0]; /* El programa aborta pues punt apunta a un bloque que ya  

no nos pertenece */ 

Errores típicos al utilizar punteros

Page 47: Tema 8 Punteros

47Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

Escribir un programa que pida un vector al usuario y una vez que éste lo haya introducido, ha de generar otro vector que contenga sólo los elementos del primer vector que sean número pares e imprimirlos por pantalla. La dimensión de ambos vectores es desconocida antes de ejecutar el programa.

#include <stdio.h>#include <stdlib.h>int main(void){

int *pvec_usu; /* Puntero al vector introducido por el usuario*/

int *pvec_par; /* Puntero al vector de elementos pares */int dim_usu; /* Dimensión del vector del usuario */int dim_par; /* Dimensión del vector de elementos pares */int i; /* Ïndice de los for */int j; /* Indice para recorrer el vector de elementos

pares */

printf("Introduzca la dimensión del vector: ");scanf("%d", &dim_usu);

Ejemplo de asignación dinámica de memoria (1/4)

Page 48: Tema 8 Punteros

48Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

/* Asignamos memoria para el vector del usuario. Contiene dim_usu enteros */

pvec_usu = (int *) calloc (dim_usu, sizeof(int));if (pvec_usu == NULL) {

printf("Error: no hay suficiente memoria");}else {

/* Pedimos los elementos del vector */for (i = 0; i < dim_usu; i++) {

printf("Elemento %d = ", i);scanf("%d", &(pvec_usu[i]));

}

/* Contamos los pares en la variable dim_par */dim_par = 0;for (i=0; i < dim_usu; i++) {

if ((pvec_usu[i] % 2) == 0) { /* Es par */dim_par++;

}}

Ejemplo de asignación dinámica de memoria (2/4)

Page 49: Tema 8 Punteros

49Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

/* Se asigna memoria para los números pares */pvec_par = (int *)calloc(dim_par, sizeof(int));if (pvec_par == NULL) {

printf("Error: no hay suficiente memoria”);free(pvec_usu);

/* Antes de salir, liberar la memoria ya asignada */}else {

/* Se copian los elementos pares */j = 0; /* Índice del primer elemento del vector de pares */for (i=0; i < dim_usu; i++) {

if ((pvec_usu[i] % 2) == 0) { /* Es par *//* Se copia el elemento */pvec_par[j] = pvec_usu[i]; /* Incremento el indice del vectorpares*/j++;

}}

Ejemplo de asignación dinámica de memoria (3/4)

Page 50: Tema 8 Punteros

50Departamento de Sistemas InformáticosEscuela Técnica Superior de Ingeniería ICAI

Tema 8: Punteros

/* Se imprime el vector de elementos pares */for (i = 0; i < dim_par; i++) {

printf("Elemento par %d = %d \n", i, pvec_par[i]);

}

/* Antes de salir, se libera la memoria asignada */free(pvec_usu);free(pvec_par);

}/* del else de la segunda asignación”} /* del else de la primera asignación*/

printf("\n Fin del programa ");return 0;

}

Ejemplo de asignación dinámica de memoria (4/4)

Page 51: Tema 8 Punteros

Escuela Técnica Superior de Ingeniería ICAIAlberto Aguilera 2528015 MadridTel +34 91 542 28 00Fax + 34 91 542 31 76Iwww.icai.upcomillas.es

www.upcomillas.es