Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un...

99
Informática II Ingeniería Electrónica 2011

Transcript of Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un...

Page 1: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Informática II

Ingeniería Electrónica 2011

Page 2: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Un puntero es una variable que contiene la dirección de otra

Se usan mucho en C en parte porque: A veces constituyen la única forma de

expresar una operación En parte, debido a que, por lo general

generan un código más compacto y eficiente de lo que puede obtenerse en otras formas

Page 3: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

Una computadora típica tiene un arreglo de celdas de memoria numeradas o direccionadas consecutivamente, que pueden manipularse individualmente o en grupos contiguos.

La declaración int *p; Indica que p es un puntero que apunta a un

entero. El valor de p es una dirección de comienzo de una

celda de memoria, el contenido almacenado en dicha dirección es de tipo int

Page 4: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

int *p; puede leerse de dos formas: *p es un entero (* es el operador de

indirección o desreferencia), *p es una expresión

p es un int * (p es una variable) Ambas interpretaciones son

equivalentes

Page 5: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

La sentencia p=&x; Indica que p apunta a x (asigna la

dirección de x a la variable p) El operador & sólo se aplica a objetos

que están en memoria: variables y elementos de arreglos. No puede aplicarse a expresiones, constantes o variables de tipo register

Page 6: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

void main(){int x=1, y=2; int z[3]={1,2,3};int *p;//p puntero a enterop=&x;//p apunta ahora a xy=*p;//y ahora vale igual que x=1*p=0;// x ahora vale 0p=&z[0];//p ahora apunta a z[0]//podría haber escrito p=z;}

Page 7: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

Si p apunta al entero x, *p puede presentarse en cualquier contexto donde x pueda hacerlo, así que (por ahora *p es una forma indirecta de referirme a x)

*p=*p+10;//ídem a x=x+10; Incrementa el *p (el valor de la variable a la

que apunta p, o sea el valor de x) en 10 Los operadores unarios * y & se ligan más

estrechamente que los aritméticos Así y=*p+1;//toma lo que apunta p, le agrega 1

y //asigna el resultado a y, ídem y=x+1;

Page 8: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

*p+=1;//ídem a x+=1;ídem a *p=*p+1; ++*p;// ídem ++x;ídem *p=*p+1; (*p)++;//ídem x++;, los () son necesarios, sin

ellos la expresión incrementaría p en lugar de a lo que p apunta, debido a que los operadores unarios como * y ++ se asocian de derecha a izquierda

*p++;//ídem *(p++);aritmética de punteros

Page 9: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y direcciones

Puesto que los punteros son variables pueden emplearse sin desreferenciamiento. Por ejemplo, si q es otro puntero a entero: q=p;

Copia el contenido de p en q, así hace que q apunte a lo que p esté apuntando

Ojo! La declaración int *p, q; declara a p como puntero a int y q como

int

Page 10: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y argumentos de funciones

C pasa los argumentos de funciones por valor, no existe forma directa para que la función que se invoca altere una variable de la función que la llama.

Por ejemplo una rutina de ordenamiento podría intercambiar dos elementos desordenados con una función

Page 11: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y argumentos de funciones

Page 12: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y argumentos de funciones

La función anterior sólo cambia copias de a y b! No sirve

La forma de obtener los resultados deseados es: el programa invocador pase punteros a los valores que se intercambian (o sea direcciones de memoria de variables del mismo tipo que el puntero)

Page 13: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y argumentos de funciones

Page 14: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y argumentos de funciones

Aplicaciones: poder devolver más de un valor

int edad; double altura; scanf(“%d %lf”,&edad, &altura);

Page 15: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

#include <stdio.h>

void conversor(int*h, int*m, int*s);

void main(){

int segundos, minutos, horas,auxiliar;

printf("Ingrese un nro.entero de segundos para convertir a horas: ");

scanf("%d",&segundos);

auxiliar=segundos;//conversor cambia el valor inicial de segundos!

conversor(&horas, &minutos, &segundos);

printf("En %d segundos hay: %d horas, %d minutos y %d segundos\n", auxiliar, horas,

minutos,segundos);

}

void conversor(int*h, int *m, int *s)

{

int resto;

*h=*s/3600; //división entera

resto=*s%3600;//* tiene mayor precedencia que / y %

*m=resto/60;

*s=resto%60;

}

Page 16: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

En C existe una fuerte relación entre punteros y arreglos, deben discutirse simultáneamente.

Cualquier operación que pueda lograrse por indexación de un arreglo también puede realizarse con punteros.

La versión con punteros por lo general es más rápida

Page 17: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

La declaración int a[10]; define un arreglo a de tamaño 10, un bloque de 10 objetos consecutivos llamados: a[0], a[1], ..., a[9]

La notación a[i] se refiere al término i-ésimo elemento del arreglo a. Si pa es un puntero a entero declarado como:

int *pa; La asignación pa=&a[0]; hace que p apunte

al elemento 0 de a, o sea pa contiene la dirección de a[0]

Page 18: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Ahora la asignación x=*pa; copia el contenido de a[0] en x

Si pa apunta a un elemento en particular de un arreglo, entonces, por definición pa+1 apunta apunta al siguiente elemento, pa+i apunta i elementos después de pa, pa-i apunta a i elementos antes

Page 19: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Así si pa apunta a a[0] entonces *(pa+1) se refiere al contenido de a[1], pa+i es la dirección de a[i] y *(pa+i) es el contenido de a[i]

Esto es cierto sin importar el tipo o tamaño de las variables del arreglo a.

El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente objeto y pa+i apunta al i-ésimo objeto delante de pa

Page 20: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

La correspondencia entre indexación y aritmética de punteros es muy estrecha.

Por definición el valor de una variable o expresión de tipo arreglo es la dirección del elemento 0 del arreglo. Así que después de la asignación pa=&a[0];

pa y a tienen valores idénticos. Puesto que el nombre de un arreglo es sinónimo de la localidad del elemento inicial puede también escribirse como pa=a;

Page 21: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Una referencia a a[i] también puede escribirse como *(a+i). Al evaluar a[i] C la convierte inmediatamente a *(a+i)!; las 2 formas son equivalentes.

Al aplicar el operador & a ambas partes de esta equivalencia, se deriva que &a[i] y a+i son también idénticas; a+i es la dirección del i-ésimo elemento delante de a

Si pa es un puntero, las expresiones pueden usarlo con un subíndice, pa[i] es idéntico a *(pa+i)

Page 22: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

En resumen, cualquier expresión de arreglo e índice es equivalente a una expresión escrita como un puntero y un desplazamiento (offset)

Existe una diferencia entre un nombre de arreglo y un puntero, que debe tenerse en mente. Un puntero es una variable por esto pa=a; y pa++; son legales.

El nombre de un arreglo no es una variable, por tanto a=pa; y a++ son ilegales

Page 23: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Cuando un nombre de un arreglo se pasa a una función lo que se pasa es la localidad del elemento inicial.

Dentro de la función que se invoca, este argumento es una variable local y por tanto, un parámetro de nombre de arreglo es un puntero, o sea, una variable que contiene una dirección

Page 24: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

/*strlen: regresa la longitud de s*/int strlen(char s[]){

int i=0;while(s[i]!=‘\0’)

++i; return i;}

Page 25: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Page 26: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Puesto que s es un puntero es perfectamente legal incrementarlo; s++ no tiene efecto alguno sobre la cadena de caracteres de la función que llamó a strlen, sólo incrementa la copia privada del puntero de strlen

Llamadas como estas, funcionan: strlen(“hola mundo”);//constante de cadena strlen(array);//char array[100];puntero o array? strlen(ptr); //char *ptr;más explícita la llamada

Page 27: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Puesto que los parámetros formales en una definición de función char s[]; y char *s; son equivalentes preferimos este último porque indica más explicitamente que el parámetro es un puntero.

Cuando un nombre de arreglo se pasa a una función ésta puede interpretar a su conveniencia que se ha manejado un arreglo o un puntero y manipularlo en consecuencia. Puede incluso manejar ambas notaciones si ello lo hace apropiado y claro

Page 28: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Es posible pasar parte de un arreglo a una función, pasando un puntero al inicio del subarreglo. Por ejemplo, si a es un arreglo f(&a[2]) y f(a+2) ambas pasan a f la dirección del subarreglo que se inicia en a[2].

Dentro de f la declaración de parámetros puede ser f(int arr[]){...} o f(int *arr){...}

En lo que concierne a f el hecho de que el parámetro se refiera a parte de un arreglo más grande no es de consecuencia

Page 29: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros y arreglos

Si está seguro que los elementos existen, también es posible indexar hacia atrás en un arreglo, p[-1], p[-2],etc., son legítimos desde el punto de vista sintáctico y se refieren a elementos que preceden inmediatamente a p[0].

Por supuesto es ilegal hacer referencia a objetos que no estén dentro de los límites del arreglo

Page 30: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

4 versiones equivalentes

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

int vector[10]={1,2,3,4,5,6,7,8,9,10};int i,suma=0;double promedio;for(i=0;i<10;i++)

suma+=vector[i];promedio=suma/(double)10;printf("El promedio es: %lf\n",promedio);

return 0;}

Page 31: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

4 versiones equivalentes

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

int vector[10]={1,2,3,4,5,6,7,8,9,10};int i,suma=0;double promedio;for(i=0;i<10;i++)

suma+=*(vector+i);promedio=suma/(double)10;printf("El promedio es: %lf\n",promedio);

return 0;}

Page 32: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

4 versiones equivalentes

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

int vector[10]={1,2,3,4,5,6,7,8,9,10};int i,*p,suma=0;p=vector;double promedio;for(i=0;i<10;i++)

suma+=*(p+i);promedio=suma/(double)10;printf("El promedio es: %lf\n",promedio);

return 0;}

Page 33: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

4 versiones equivalentes

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

int vector[10]={1,2,3,4,5,6,7,8,9,10};int i,*p,suma=0;p=vector;double promedio;for(i=0;i<10;i++)

suma+=p[i];promedio=suma/(double)10;printf("El promedio es: %lf\n",promedio);

return 0;}

Page 34: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Si p es un puntero a algún elemento de un arreglo entonces p++ incrementa p para apuntar al siguiente elemento y p+=i la incrementa para apuntar a i elementos delante de donde actualmente lo hace. Esas y otras construcciones semejantes son las formas más simples de aritméticas de punteros o de direcciones

Page 35: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

El lenguaje C es consistente y regular en su enfoque a la aritmética de direcciones; su integración de punteros, arreglos y aritmética de direcciones es uno de los aspectos que le dan fuerza

La aritmética de punteros es consistente, si p es un puntero a int (float), entonces p++ avanza al siguiente int (float)

Todas las manipulaciones de punteros automáticamente tiene en cuenta el tamaño (sizeof) de los objetos a los que apuntan

Page 36: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Las operaciones válidas de punteros son asignación de punteros del mismo tipo, suma y resta de un puntero con un entero, resta o comparación de dos punteros a miembros del mismo arreglo y asignación o comparación con 0.

Toda otra aritmética de punteros es ilegal. No es legal sumar 2 punteros, multiplicarlos o dividirlos, enmascararlos o agregarles un float o un double o asignar un puntero de un tipo a otro tipo sin un cast

Page 37: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Page 38: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Page 39: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Page 40: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Page 41: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

En general un puntero puede inicializarse tal como cualquier otra variable aunque, normalmente los únicos valores significativos son 0 o una expresión que involucre la dirección de un dato previamente definido y de un tipo apropiado

Page 42: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

El lenguaje C garantiza que cero nunca es una dirección válida para datos

La constante simbólica NULL se emplea con frecuencia en lugar de 0 como un mnemónico para indicar más claramente que es un valor especial para un puntero; está definida en stdio.h

Page 43: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Los punteros pueden compararse bajo ciertas circunstancias. Si p y q apuntan a miembros de un mismo arreglo, entonces relaciones como ==, !=, <,<=,etc, funcionan correctamente

p<q es verdadero si p apunta a un elemento que está antes en el arreglo de lo que está al que apunta q. Cualquier puntero puede compararse por su igualdad o desigualdad con 0. Pero está indefinido el comportamiento para la aritmética o comparaciones con punteros que no apuntan a miembros del mismo arreglo

Page 44: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

Como ya se vio un puntero y un entero pueden sumarse o restarse. La construcción p+n significa la dirección del n-ésimo objeto adelante del que apunta actualmente p. Esto es verdadero sin importar la clase de objeto al que apunta p.

n es escalada de acuerdo con el tamaño de los objetos a los que apunta p, lo cual está determinado por la declaración de p. Por ej. Si p es puntero a int que ocupa 4 bytes, la escala para el int será de 4

Page 45: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Aritmética de direcciones

La resta de punteros también es válida: si p y q apuntan a elementos del mismo arreglo y p<q entonces q-p+1 es el número de elementos desde p hasta q inclusive.

En strlen p-s da el número de caracteres que se avanza desde el comienzo de la cadena, es decir, su longitud

Page 46: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros, arreglos y funciones

Page 47: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a caracteres y funciones

Una constante de cadena escrita como “Soy una cadena” es un arreglo de caracteres. En la representación interna el arreglo termina con el carácter nulo ‘/0’ de tal manera que los programas puedan encontrar el fin.

La longitud de almacenamiento es así uno más que el número de caracteres entre comillas

En printf(“hola mundo\n”); el acceso a la cadena de caracteres constante que se le pasa a printf el acceso a ella es a través de un puntero a char que apunta al inicio de la misma

Page 48: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a caracteres y funciones

El lenguaje C no proporciona ningún operador para procesar como una unidad una cadena de caracteres

Por ejemplo: char mensaje[]=“hola” //como array char *pmensaje=“hola”; //puntero mensaje es un arreglo suficientemente grande

como para contener el texto y el ‘\0’ que lo finaliza. Se pueden modificar caracteres individuales dentro del arreglo pero mensaje siempre se refiere a la misma localidad de almacenamiento

Page 49: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a caracteres y funciones

Por otro lado, pmensaje es un puntero inicializado para apuntar a una cadena constante, el puntero puede modificarse posteriormente para que apunte a otro lado, pero el resultado es indefinido si trata de modificar el contenido de la cadena

Page 50: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Page 51: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Page 52: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Aquí hay punteros (los argumentos reales) convenientemente inicializados que se desplazan a lo largo del arreglo un carácter a la vez, hasta que el ‘\0’ (incluído) con que termina t se ha copiado a s

En la práctica strcpy no se escribiría así, los programadores expertos en C preferirían:

Page 53: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Page 54: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Esto traslada el incremento de s y t hacia adentro de la parte de prueba del lazo. El valor de *t++ es el carácter al que apunta t antes de incrementarse, el ++ postfijo no modifica t sino hasta después de que se ha tomado el carácter. En la misma forma, el carácter se almacena en la posición anterior de s antes de que s se incremente. También este carácter es el valor contra el cual se compara ‘\0’ para control del ciclo El efecto real es que los caracteres se copian de t a s, hasta el ‘\0’ inclusive

Page 55: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Page 56: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcpy

Finalmente como la comparación contra ‘\0’ es redundante se la modifica, puesto que la pregunta del lazo es simplemente si la expresión es 0

Debe dominarse este estilo puesto que es la que encontrará frecuentemente en programas escritos en C!!

Page 57: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcmp

Page 58: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

strcmp

Page 59: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Arreglos de punteros

Puesto que en sí mismo los punteros son variables pueden almacenarse en arreglos tal como otras variables

El uso más común es el de formar arreglos de cadenas de caracteres

Cada entrada en el arreglo es un apuntador al primer carácter de la cadena

Page 60: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Arreglos de punteros

Sea la declaración: char * mensaje[4] = {''Hola'',''Adios'',''Bye'',''Salut''}

Cada cadena está almacenada en memoria como una cadena de caracteres terminada en ‘\0’.

En el arreglo no están colocadas las cadenas, tan solo están almacenados los apuntadores

Page 61: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Arreglos de punteros

Aunque el arreglo es de tamaño fijo, permite el acceso a cadenas de caracteres de cualquier longitud

Los arreglos de apuntadores son una representación de datos que manejan de una forma eficiente y conveniente líneas de texto de longitud variable

Page 62: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Ordenar líneas de un texto

Page 63: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

swap

/*swap, intercambia v[i] y v[j]*/void swap(char *v[], int i, int j){char *temp;//puntero a chartemp=v[i];//copia de punterosv[i]=v[j];v[j]=temp;}

Page 64: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

2º ejemplo#include <stdio.h>#include <string.h> void main(void){ /* declaracion de variables*/ int i; int respuesta = 0; char ciudad[31]; char *lista[5] = {“Acapulco”, “Chilpancingo”, “Iguala”, “Zihuatanejo”, “Taxco”};//puedo no poner la dimensión 5 //lista[1]almacena un puntero a la 2º cadena de lista (almacena la dirección de //memoria de esa cadena) printf(“\nEscriba una de las cinco ciudades mas“); printf(“\nimportantes del Estado de Guerrero:\n“); gets(ciudad); for (i=0; i<5; i++)

if (!strcmp(lista[i], ciudad))respuesta = 1;

if (respuesta)printf(“\nCorrecto, felicidades\n”);

elseprintf(“\nLo siento, es incorrecto.\n”);

}

Page 65: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

3º ejemplo

#include <stdio.h>#include <string.h>int diadelasemana(int m,int d, int y);int main(){

struct fecha{int dia;int mes;int año;char diasem[10];

};

Page 66: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

3º ejemplo

struct fecha actual;char* meses[]={"enero","febrero","marzo","abril","mayo","junio","julio","agosto","setiembre","octubre","noviembre","diciembre"};char *diasemana[]={"domingo","lunes","martes","miercoles","jueves","viernes","sabado","domingo"};printf("ingrese en formato entero una fecha como:mm/dd/yyyy: ");scanf("%d/%d/%d",&actual.mes,&actual.dia,&actual.año);int d=diadelasemana(actual.mes,actual.dia,actual.año);strcpy(actual.diasem,diasemana[d]);printf("\nLa fecha completa es: %s %d de %s de %d\n",actual.diasem,actual.dia,meses[actual.mes-1],actual.año);

return 0;}

Page 67: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

3º ejemplo

int diadelasemana(int m, int d, int y){ //sirve para año mayor a 1582//retorna un valor entre 0 y 6

int a=(14-m)/12;y-=a;m+=(12*a)-2;return (d+y+(y/4)-(y/100)+(y/400)+(31*m/12))%7;

}

Page 68: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a punteros

Un puntero a puntero (o doble puntero) es…

un puntero que contiene la dirección de memoria de otro puntero

Page 69: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a punteros

Page 70: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a punteros

Page 71: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Punteros a punteros

Un arreglo de punteros no es más que un puntero a punteros. El nombre del arreglo es la dirección de la primer elemento del array que apunta a los demás a medida que se incrementa

Es una forma de indirección múltiple que puede llevarse al nivel que se desee (código difícil de leer y propenso a errores)

Page 72: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

Todos los elementos que forman parte de un programa en C se sitúan en memoria en zonas diferentes:

El segmento de código es un trozo fijo de memoria donde se ubica el código compilado del programa

Los objetos globales y los declarados static, se colocan en el segmento de datos y la gestión de su espacio de memoria se realiza en la fase de compilación-enlazado. Ellos ocupan esa zona de memoria mientras dura la ejecución del programa

Page 73: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

La asignación de memoria de los objetos locales, los ubicados en la pila (stack) o en los registros, se realiza en la fase de ejecución. Su ubicación es temporal, es decir, mientras permanece activo el bloque o función que incluye al objeto. Recuerde que los objetos locales tienen almacenamiento automático (auto) o register, explícita o implícitamente.

Page 74: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

El montón (heap) es un trozo de memoria extra donde se ubican los llamados objetos dinámicos. Un objeto dinámico se caracteriza porque su asignación de memoria se realiza en tiempo de ejecución, lo cual supone la creación dinámica del objeto.

Page 75: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

Mientras que la gestión de memoria estática en la pila o en los registros la realiza el propio sistema, la creación de objetos dinámicos es responsabilidad del programador, debiendo preocuparse además de su destrucción.

Destruir el objeto supone devolver la memoria usada para su almacenamiento cuando ya no se necesite

Page 76: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

Para asignar memoria dinámicamente se usan las funciones que trabajan con el puntero genérico void * y que están en el archivo de cabecera stdlib.h

void *calloc(size_t nobj, size_t size), calloc obtiene (reserva) espacio en memoria para alojar un vector de nobj objetos, c/u de tamaño size. Si no hay memoria disponible se devuelve NULL. El espacio reservado se inicializa a bytes de 0s. Obsérvese que calloc devuelve un (void *) y que para asignar la memoria que devuelve a un tipo Tipo_t hay que realizar el cast: (Tipo_T *)

Page 77: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

Ejemplo: char * c;c = (char *) calloc (40, sizeof(char)); void *malloc(size_t size), malloc funciona

de forma similar a calloc salvo que: no inicializa el espacio y es necesario saber el tamaño exacto de las posiciones de memoria solicitadas.

Page 78: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

El ejemplo anterior se puede reescribir:char * c;c = (char *) malloc (40*sizeof(char));

void *realloc(void *p, size_t size), realloc cambia el tamaño del objeto al que apunta p y lo hace de tamaño size. El contenido de la memoria no cambiará en las posiciones ya ocupadas. Si el nuevo tamaño es > que el antiguo, no se inicializan a ningún valor las nuevas posiciones. En el caso en que no hubiese suficiente memoria para “realojar” al nuevo puntero, se devuelve NULL y p no varía. El puntero que se pasa como argumento ha de ser NULL o bien un puntero devuelto por malloc(), calloc() o realloc().

Page 79: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

void free(void *p) free() libera el espacio de memoria al

que apunta p. Si p es NULL no hace nada. Además p tiene que haber sido “alojado” previamente mediante malloc(), calloc() o realloc().

Page 80: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

El siguiente código construye un vector de enteros del tamaño que indica el usuario por teclado, rellena el vector con los datos que introduce el usuario, amplia el tamaño del vector y sigue rellenando, y finalmente, libera el espacio de memoria ocupado por el vector. (De:studies.ac.upc.edu/EPSC/TCP/documentos/MemoriaDinamica.doc)

Page 81: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria#include <stdio.h>#include <stdlib.h>void main (){ // declaramos un puntero a un entero

int *vector;int num_elem=0;int i, mas;

  printf ("Escribe el numero de elementos del vector\n");scanf ("%d",&num_elem);

  // Ahora se el tamaño inicial del vector. Reservo espacio de memoria vector = (int *) malloc (num_elem*sizeof (int));if (vector == NULL)

printf ("Operacion incorrecta");

Page 82: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

else{

// cargo el vector con los datos leidos del teclado

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

printf ("Escribe siguiente elemento:\n ");

scanf ("%d",&vector[i]);

};

// Añado más elementos

printf ("¿Cuantos elementos quieres añadir?\n");

scanf ("%d",&mas);

// reajusto el tamaño del vector

vector = (int *) realloc (vector, (num_elem+mas)*sizeof (int));

Page 83: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Gestión dinámica de memoria

if (vector == NULL)

printf ("Operacion incorrecta");

else{

for (i=num_elem; i<num_elem+mas; i++){

printf ("Escribe siguiente elemento:\n ");

scanf ("%d",&vector[i]);

}

num_elem = num_elem + mas;

}}

// ya no necesito el vector y libero el espacio de memoria

free (vector);}

Page 84: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Arrays y asignación dinámica

A veces reservar memoria estática para arreglos (declarados suficientemente grandes aún a sabiendas de que no va a usarse toda la memoria reservada).

La gestión dinámica de memoria (arrays dinámicos) permite asignar memoria en tiempo de ejecución a medida que se vaya necesitando

Page 85: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Arrays y gestión dinámica de memoria

Para usar arreglos dinámicos: Se declara un puntero en vez de un arreglo

(inicialmente apunta a cualquier lado) Se pide la memoria necesaria para el arreglo

(calcularla) a partir del puntero declarado anteriormente (ahora apunta al comienzo de este trozo)

Debe asegurarse que efectivamente se dispone de ella

En caso afirmativo se procesa Se libera la memoria cuando no se necesite

Page 86: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

En el ejemplo

La función malloc nos da la dirección de memoria donde comienza el espacio que ha reservado, y asignamos esa dirección al puntero vector. Fijate que la palabra malloc está precedida por (int *) para indicar simplemente que la función malloc retornará un apuntador a un entero.

Page 87: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

En el ejemplo...

Si la función malloc ha tenido problemas para buscar el espacio de memoria (por ejemplo, no ha encontrado espacio suficiente) entonces malloc retorna el valor NULL. Debemos, por tanto, asegurarnos de que la operación de reserva de memoria ha funcionado bien antes de empezar a usar el vector.

Si la operación de reserva de memoria ha funcionado bien, entonces podemos ya usar el vector exactamente igual que si fuese un vector estático, con la diferencia de que ahora el vector ocupa exactamente el espacio que ha elegido el usuario una vez iniciada la ejecución del programa.

Page 88: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

En el ejemplo...

int *vector;

0 n-1

vector ?

vector= (int *)malloc(n*sizeof (int));

vector

vector[3]=5;

0

vector n-1 3

5

vector[3]=5;

0

vector MAX-1 3

5

int vector[MAX]; 0

vector MAX-1

Page 89: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

En el ejemplo

La figura compara el funcionamiento de los vectores estáticos y dinámicos. A la izquierda se muestra cómo al declarar un vector estático el computador automáticamente reserva espacio en memoria según el tamaño establecido en la declaración, y crea la variable que apunta a ese espacio, para poder acceder después durante le programa. A la derecha se muestra como, en el caso de los vectores dinámicos, primero se crea la variable que apuntará al vector, después se reserva el espacio justo que se necesite, se hace que la variable apunte al espacio y se accede al vector con normalidad.

Page 90: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

En el ejemplo...

En la segunda parte del programa vemos qué hay que hacer en el caso de que necesitemos ampliar el tamaño del vector. Lo que haremos es usar la función realloc, a la que pasamos como parámetro el apuntador al inicio del vector cuyo tamaño queremos cambiar, y el nuevo tamaño que queremos que tenga ese vector. El computador buscará espacio para el nuevo vector y nos devolverá la dirección del sitio donde estará el vector. Como es lógico, las num_elem primeras posiciones del vector ampliado contendrán la misma información que había en el vector antes de la ampliación.

Page 91: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

En el ejemplo...

Finalmente, cuando ya he terminado de trabajar con el vector, podemos llamar a la función free para liberar el espacio de memoria ocupado por el vector, de forma que ese espacio pueda ser usado para otras operaciones.

En algunas ocasiones, en lugar de hacer crecer el vector querrás reducir su tamaño. El mecanismo es el mismo: llamarás a la función realloc indicando el nuevo tamaño del vector, que será menor que el que tenía antes.

Page 92: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Matrices dinámicas

En algunos casos trabajaremos con matrices, y también querremos que se ajusten al tamaño estrictamente necesario. Veamos ahora cómo trabajar con matrices dinámicas (es un poco más complicado que el caso de los vectores)

Page 93: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Matrices dinámicas

matriz

Fila 0

Fila N-1

matriz[1,M-1]

Page 94: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Matrices dinámicas

La figura muestra la estructura que tiene una matriz dinámica de N filas y M columnas. La variable matriz es un apuntador a un vector de N posiciones. Cada posición contiene un apuntador a una de las filas de la matriz. El apuntador que hay en primera posición de ese vector apunta al espacio de memoria donde están los M elementos de la fila 0 de la matriz.

Page 95: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

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

int **matriz;int N,M;int i,j;printf ("Escribe el numero de filas y el número de columnas\n");scanf ("%d %d",&N, &M);

  // Ahora se el tamaño inicial de la matriz. // Reservo espacio para el vector de apuntadores a las //filas

matriz=(int **) malloc (N*sizeof (int *));if (matriz== NULL)printf ("Operacion incorrecta");else{

Page 96: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Ejemplo

// ahora reservo espacio para cada una de las filasfor (i=0; i<N; i++){

matriz[i]=(int *) malloc (M*sizeof (int));if (matriz[i]== NULL)

printf ("Operacion incorrecta");}  // ahora le pido al usuario los datos de la matriz

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

printf ("Elemento %d,%d: ",i,j);scanf ("%d",&matriz[i][j]);}

 // cuando termino de trabajar con el vector, //libero el espacio de memoria

free (matriz);}}

Page 97: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Matrices dinámicas

Observa 1º la declaración de la variable matriz: un apuntador a un vector que contiene apuntadores a enteros. Por eso se escribe con dos * (apuntador a un apuntador).

El programa pide al usuario el tamaño de la matriz (N filas y M columnas), y reserva espacio para un vector de N apuntadores a enteros. El tamaño de cada uno de los elementos de ese vector de apuntadores es sizeof (int *) (el tamaño de un apuntador a entero).

Page 98: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Matrices dinámicas

Ahora lo que tiene que hacer es reservar el espacio necesario para cada una de las filas de la matriz. Para ello se ejecuta un bucle que hace tantas iteraciones como filas. En cada iteración reserva espacio para una fila (un vector de M números enteros), y pone el apuntador obtenido en la posición correspondiente del vector de apuntadores a filas (matriz[i])

Page 99: Informática II - UNR...de las variables del arreglo a. El significado de “agregar 1 a un puntero” y por extensión toda la aritmética de punteros es que, pa+1 apunta al siguiente

Matrices dinámicas

Después de todo esto ya tenemos construida la matriz dinámica y podemos acceder a ella comos si fuese estática. Fíjate por ejemplo cómo accedemos a ella para poner los datos leídos del teclado