Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa...

155
Punteros

Transcript of Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa...

Page 1: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros

Page 2: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

John Von Neumann

• 1903-1957

• Matemático

• Publicó la idea de programa almacenado en memoria (1945)

Page 3: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Lineamientos del Modelo de Von Neumann

• Los datos y programas se almacenan en una misma memoria de lectura-escritura

• Los contenidos de esta memoria se direccionan indicando su posición sin importar su tipo

• Ejecución secuencial (salvo que se indique lo contrario)

• Representación binaria

Page 4: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Estructura (computadora)

I/O Memoria

Address Bus

Control

CPU

Control

Data Bus

Page 5: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Organización de la memoria principal

• Conceptualmente, la memoria es un gran array de bytes , – En un byte puedo

almacenar un char

• cada byte con una dirección única (índice) – Dominio de todas las

direcciones posibles=espacio de direcciones

Page 6: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Organización de la memoria principal

• Aunque el byte es la unidad de direccionamiento, solemos hablar de palabras. Palabra se refiere al ancho de los registros generales de la CPU

– Determina el tamaño nominal de los datos de valor entero, incluyendo direcciones

Page 7: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Organización de la memoria principal

• Direccionamiento de ubicaciones de bytes en memoria

– Direccionamiento del primer byte de la palabra

• Simplificación

– Considerar endianness, alineamiento…

Page 8: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Operador sizeof

• C proporciona un operador unario a tiempo de compilación llamado sizeof que se puede emplear para calcular el tamaño en bytes de cualquier objeto

• sizeof objeto – Objeto puede ser variable, array, estructura

• sizeof (nombre de tipo) – Nombre de tipo: tipo primitivo o derivado tal

como una estructura

Page 9: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Operador &

• El operador unario & da la dirección de un objeto

• La expresión &v retorna la dirección de memoria de una variable v

• 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 10: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Entrada con formato - scanf

• int scanf(char *format, ...)

• Lee caracteres de la entrada estándar, los interpreta de acuerdo con las especificaciones que están en format, y almacena los resultados a través de los argumentos restantes, cada uno de los cuales indican dónde debe almacenarse la entrada correspondientemente convertida

Page 11: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Entrada con formato - scanf

• int day, year;

char monthname[20];

scanf("%d %s %d",&day,monthname,

&year);

• No se emplea & con monthname ya que por definición, el valor de una variable o expresión de tipo arreglo es la dirección del elemento cero del arreglo

Page 12: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Valor vs. dirección de una variable

• El nombre de una variable representa la dirección de memoria donde está almacenado el valor de dicha variable

• El valor de una variable es el contenido de la memoria asignada, y puede cambiar durante la ejecución del programa

• El tipo de dato asociado a la variable define su representación binaria, rango de valores que maneja y longitud

Page 13: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Valor vs. dirección de una variable

Page 14: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros • 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

• Reserva de memoria dinámica

• Forma alternativa a paso de argumentos por referencia

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

• Permiten representar en forma eficiente estructuras de datos sofisticadas (pilas, colas, listas, etc.)

Page 15: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y direcciones

• 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

• La sentencia p=&x;//inicialización

• Indica que p apunta a x (asigna la dirección de x a la variable p)

Page 16: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y direcciones • Es útil representar los punteros como flechas

que llegan a la dirección de memoria a la cual apuntan

• Generalmente las direcciones en memoria se indican en hexadecimal

x

p

Page 17: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y direcciones

• El operador unario * es el operador de indirección o desreferencia, cuando se aplica a un puntero, da acceso al objeto al que señala el puntero

• La declaración de un puntero p a un int, funciona como un mnemónico; dice que la expresión *p es un int

Page 18: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y direcciones int x=1, y=2; int z[3]={1,2,3}; int *p, *q;//p puntero a int, Ojo es *q, no q! p=&x;//p apunta ahora a x y=*p;//y ahora vale igual que x=1 *p=0;// x ahora vale 0 /* puedo usar p en cualquier contexto, donde x pueda hacerlo*/ *p=*p+1; //* >precedencia que +,x=x+1 //ídem a *p+=1; ídem a ++*p; ídem a (*p)++; //los () son necesarios, * y ++ (unarios) se //asocian de derecha a izquierda p=&z[0];//p ahora apunta a z[0] q=p; /*ahora q también apunta a x, uso de puntero sin desreferenciarlo*/

Page 19: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y direcciones

Page 20: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

• 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 mediante punteros

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

Page 21: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

• 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 pa apunte al elemento 0 de a, o sea pa contiene la dirección de a[0]

-1 9 300 -54 0 23 4 11 -34 -7

a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

Page 22: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

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

• Importante: 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 (aritmética de punteros o de direcciones)

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

Page 23: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

• 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.

Page 24: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

• La integración de punteros, arreglos y aritmética de direcciones en C 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 25: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

• 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 26: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays • 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 27: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

1 4 -5 0 8

p

a[0] a[1] a[2] a[3] a[4]

p+1 p+2

p+3 p+4

Page 28: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

1 4 -5 0 8

p

a[0] a[1] a[2] a[3] a[4]

p[0] p[1] p[2] p[3] p[4]

Page 29: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

Page 30: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y arrays

• 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 31: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

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: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

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 33: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

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; double promedio; p=vector; for(i=0;i<10;i++) suma+=*(p+i); promedio=suma/(double)10; printf("El promedio es: %lf\n",promedio); return 0; }

Page 34: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

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 35: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

NULL

• 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

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

Page 36: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

NULL

• 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

• Cuando NULL se asigna a un puntero significa que no apunta a nada en particular, es decir a ningún área de memoria

• Nunca trate de desreferenciar un puntero al que se le asignó NULL!, se genera un error en tiempo de ejecución (segmentation fault)

• Suele usarse como retorno de una función indicando valor erróneo

Page 37: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

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 38: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Resta de punteros

int vector[] = {28, 41, 7}; int *p0 = vector; int *p1 = vector+1; int *p2 = vector+2; //útil para determinar orden elementos array, en elementos printf("p2-p0: %d\n",p2-p0); // p2-p0: 2 printf("p2-p1: %d\n",p2-p1); // p2-p1: 1 printf("p0-p1: %d\n",p0-p1); // p0-p1: -1

Page 39: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Comparación de punteros

int vector[] = {28, 41, 7}; int *p0 = vector; int *p1 = vector+1; int *p2 = vector+2; //compara orden relativo elementos array printf("p2>p0: %d\n",p2>p0); // p2>p0: 1 printf("p2<p0: %d\n",p2<p0); // p2<p0: 0 printf("p0>p1: %d\n",p0>p1); // p0>p1: 0

Page 40: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Puntero genérico • Cada puntero señala un tipo específico de

datos, salvo “un puntero a void, void *” que se emplea para mantener cualquier tipo puntero de datos pero que en si mismo no puede desreferenciarse

• Cualquier puntero puede ser asignado a un puntero a void, luego puede realizarse un cast para volver a su tipo de puntero original:

Page 41: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Puntero genérico

Page 42: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Modelo simplificado de memoria

Page 43: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Modelo simplificado de memoria

• Todos los elementos que forman parte de un programa en C en ejecución, 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 44: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Modelo simplificado 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

Page 45: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Modelo simplificado 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 46: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Gestión dinámica de memoria

• Mientras que la gestión de memoria estática en la pila o registros la realiza el propio sistema, la creación de objetos dinámicos en el heap 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 47: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Gestión dinámica de memoria

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

• Estrictamente el operador sizeof produce un valor entero sin signo cuyo tipo está definido en stddef.h llamado size_t que, representa el máximo tamaño (en bytes) de un objeto en C

Page 48: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Gestión dinámica de memoria • 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 *) al primer byte de memoria asignada y que, para asignar la memoria que devuelve a un tipo Tipo_t, hay que realizar el cast: (Tipo_T *)

• Originalmente se creó para ayudar a asignar memoria para arrays

Page 49: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Gestión dinámica de memoria

• Ejemplo: #include <stdlib.h> //agregar

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 (basura) y es necesario saber el tamaño exacto de las posiciones de memoria solicitadas

Page 50: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Gestión dinámica de memoria

int n, i; float *ptr; printf("Ingrese la cantidad de numeros reales que desea añadir a un vector: \n"); scanf("%d",&n); ptr = (float *)malloc(n * sizeof(float)); if (NULL == ptr) {

/* No puedo asignar memoria */ printf("No puede reservar memoria para el vector\n"); return -1;

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

printf("Ingrese un nro. real para almacenar en el vector: \n"); scanf("%f",ptr+i); //ídem ptri]

}

Page 51: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Gestión dinámica de memoria

• 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(). Si el tamaño solicitado es más pequeño se devuelve memoria al heap.

Page 52: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Probar

char *string1; char *string2; string1 = (char*) malloc(16); strcpy(string1, "0123456789AB"); //primera realocación string2 = (char*) realloc(string1, 8); //luego probar añadir string2[7]='\0'; printf("string1 Value: %p [%s]\n", string1, string1); printf("string2 Value: %p [%s]\n", string2, string2); //segunda realocación string2 = (char*) realloc(string1, 64); printf("string1 Value: %p [%s]\n", string1, string1); printf("string2 Value: %p [%s]\n", string2, string2);

Page 53: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

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 54: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Fugas de memoria • Pueden ocurrir cuando se reserva memoria

dinámicamente pero nunca se libera porque: free nunca se invocó (pérdida oculta) o, porque la dirección de memoria de comienzo del bloque asignado dinámicamente se perdió.

• Esta memoria perdida no puede reclamarse para usar nuevamente y, la cantidad de memoria disponible en el heap disminuye; incluso puede llegarse a la situación de terminación del programa con la indicación out of memory tal como puede ocurrir en este ejemplo deliberado, en el que nunca se libera la memoria que se reserva indefinidamente:

Page 55: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Fugas de memoria char *chunk;

while (1) {

chunk = (char*) malloc(1000000);

printf("Allocating\n");

}

• En este otro ejemplo el puntero que se usa para reservar memoria dinámicamente se re-asigna a otra dirección provocando pérdida de memoria dinámica en el heap:

int *pi = (int*) malloc(sizeof(int));

*pi = 5;

//uso el bloque reservado para un entero

pi = (int*) malloc(sizeof(int));/*se pierde la

dirección donde almacené el 5*/

Page 56: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Fugas de memoria

• Otro ejemplo de esta causa de pérdida de memoria usando un string: se inicializa el bloque de memoria reservado dinámicamente con un literal string y, luego para mostrarlo por pantalla (recorriendo el string) se usa el mismo puntero con el cual se reservó memoria dinámicamente (name en este ejemplo) por lo cual, el puntero queda apuntando al terminador nulo de la cadena de caracteres! en lugar de al comienzo de la misma; la dirección del bloque reservado inicialmente en el heap se pierde

Page 57: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Fugas de memoria

char *name =

(char*)malloc(strlen("Susan")+1);

strcpy(name,"Susan");

while(*name != 0) {

printf("%c",*name);

name++;

}

Page 58: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros colgados

• Cuando libero memoria con free, el espacio es retornado al heap. Mientras que, el puntero puede seguir apuntando a este espacio de memoria (“dangling pointer” o referencia colgada), debe asumirse que apunta a “basura” (no apunta a ningún objeto válido) ya que esta región puede reasignarse y llenarse con datos distintos.

• Las referencias colgadas pueden provocar comportamientos indefinidos cuando se intenta acceder a la memoria referenciada; por ejemplo, puede terminar la aplicación anormalmente con una indicación de “segmentation fault” o puede ponerse en riesgo la seguridad.

• Hacer un debug de problemas inducidos por punteros puede ser dificultoso

• Este problema de referencias colgadas también se presenta al intentar retornar un puntero a una variable local a una función y luego de invocarse dicha función.

Page 59: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros colgados

int *pi = (int*)

malloc(sizeof(int));

*pi = 5;

printf("*pi: %d\n", *pi);

free(pi);

*pi = 10; //resultado impredecible

Page 60: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros colgados

• Un ejemplo más insidioso de este problema se tiene con dos punteros apuntando al mismo bloque de memoria asignado dinámicamente (alias): p1 = (int*) malloc(sizeof(int));

*p1=5;

int *p2 = p1;

...

free(p1);

...

*p2 = 10; // Dangling pointer

Page 61: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Doble free

• Se llama así al intento de liberar 2 veces la misma memoria asignada. Se produce una excepción en tiempo de ejecución

int *pi = (int*)

malloc(sizeof(int));

*pi = 5;

free(pi);

...

free(pi);

Page 62: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Doble free

• Un ejemplo menos obvio se tiene cuando hay 2 punteros apuntando al mismo área de memoria. Al tratar de liberar la memoria dinámica por 2º vez se produce una excepción p1 = (int*) malloc(sizeof(int));

*p1=5;

int *p2 = p1;

free(p1);

...

free(p2);

Page 63: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Strings en C

s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9]

H i M o m ! \0 ? ?

char s[10]

Page 64: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Declaración de un string en C • Como un array de caracteres con terminador nulo

(1 byte extra a su longitud) – char header[32]; /*puedo almacenar

hasta 31 caracteres*/

• Como un puntero – char *header; //falta inicializar

• Como un literal – “Hello world!\n”,

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

Page 65: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Inicialización de un string • Si se declaró como array de tipo char

– char header[] = "Media Player";/*se reservan 13 bytes*/

– Se pueden modificar caracteres individuales dentro del arreglo pero header siempre se refiere a la misma localidad de almacenamiento. Otra forma para esto:

– char header[13];//incluir string.h

strcpy(header,"Media Player");

– Más tedioso: inicializar caracter a caracter con literales tipo char (‘a’)

– Ingreso desde la entrada estándar char command[16];

printf("Enter a Command: ");

scanf("%s", command);//toma hasta un blanco

Page 66: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Inicialización de un string • Si se declaró como un puntero a char

– Uso de memoria dinámica

//incluir string.h

//no use sizeof para un string (char*)!

//use strlen de string.h

char *header = (char*)

malloc(strlen("Media Player")+1);

strcpy(header,"Media Player");

– O de esta forma

char *header = (char*) malloc(13);

//luego usar strcpy

Page 67: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Inicialización de un string

• La dirección de un literal puede asignarse directamente a un puntero a char – char *header = "Media Player";

• header 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

• Si se ingresa un string (puntero) por entrada estándar (scanf, gets), 1º deberá reservarse espacio dinámicamente

Page 68: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Conversiones de strings • La función sprintf realiza las mismas conversiones

que printf, pero almacena la salida en una cadena (debe ser lo suficientemente grande), en lugar de hacerlo en la salida estándar

• int sprintf(char ‘cadena, char *format, argv

arg2, ...)

• Existe también una función sscanf que lee de una cadena y no de la entrada estándar

• int sscanf(char ‘cadena, char *format, argv

arg2, ...)

• Rastrea la cadena de acuerdo con el formato en format, y almacena el valor resultante a través de argv, arg2, etc. Estos argumentos deben ser punteros.

Page 69: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

#include <stdio.h> int main() { char str[10]; /* MUST be big enough to hold all the characters of your number!! */ int i; i = sprintf(str, "%o", 15); printf("15 in octal is %s\n", str); printf("sprintf returns: %d\n\n", i); i = sprintf(str, "%d", 15); printf("15 in decimal is %s\n", str); printf("sprintf returns: %d\n\n", i); i = sprintf(str, "%x", 15); printf("15 in hex is %s\n", str); printf("sprintf returns: %d\n\n", i); i = sprintf(str, "%f", 15.05); printf("15.05 as a string is %s\n", str); printf("sprintf returns: %d\n\n", i); return 0; }

Page 70: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

#include <stdio.h> int main() { char* ints = "20, 40, 60"; char* floats = "10.4, 24.66"; char* hex = "FF, F"; int i,n,h; float f; char* s; i = sscanf(ints, "%d", &n); printf("n: %d\n", n); printf("sscanff returns: %d\n\n", i); i = sscanf(floats, "%f", &f); printf("f: %f\n", f); printf("sscanff returns: %d\n\n", i); i = sscanf(hex, "%x", &h); printf("h: %d\n", h); printf("sscanff returns: %d\n\n", i); i = sscanf(ints, "%s", s); printf("s: %s\n", s); printf("sscanff returns: %d\n\n", i); return 0; }

Page 71: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Conversión de un string a un entero

#include <stdio.h> #include <stdlib.h> int main() { char str[10]; /* MUST be big enough to hold all the characters of your number!! */ printf("15 in binary is %s\n", itoa(15, str, 2)); printf("15 in octal is %s\n", itoa(15, str, 8)); printf("15 in decimal is %s\n", itoa(15, str, 10)); printf("15 in hex is %s\n", itoa(15, str, 16)); return 0; }

Page 72: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros

• Puesto que en sí mismo los punteros son variables pueden almacenarse en arreglos tal como los otros tipos de variables int* arr[5]; int i; for(i=0; i<5; i++) {

arr[i] = (int*)malloc(sizeof(int)); //arr[i] indica direcciones, es un puntero printf("%p ",arr[i]); //*arr[i] indica contenido de la dirección //indicada por arr[i] (desreferencia) *arr[i] = i;

}

Page 73: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros

• El uso más común de un array de punteros es el de formar arreglos de cadenas de caracteres

• Cada entrada en el arreglo es un puntero al primer carácter de cada cadena

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 punteros a ellas (sus direcciones de comienzo)

Page 74: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros

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

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

Page 75: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros

Abcdefghi

xyz

Qwertyuiopasdfg

Abcdefghi

xyz

Qwertyuiopasdfg

Page 76: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

• Un puntero a puntero (o doble puntero) es un puntero que contiene la dirección de memoria de otro puntero

Page 77: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

Page 78: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

Page 79: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

• 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)

• 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

Page 80: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

http://hpc.aut.uah.es/~jgallego/LabAR/Prac_1/P1.08-Punteros_en_lenguaje_C.pdf

Page 81: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

http://www.lcc.uma.es/~pscp/doc/cavanzado.pdf

Page 82: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros • En el ejemplo de array de punteros

int main(){ int* arr[5]; int i; for(i=0; i<5; i++) { arr[i] = (int*)malloc(sizeof(int)); *arr[i] = i; printf("(arr+%d) es:%p, *(arr+%d) es: %p y **(arr+%d)es: %d\n",i,(arr+i), i,*(arr+i),i, **(arr+i)); }

Page 83: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a punteros

• En las siguiente tabla relacionada con el ejemplo anterior observe las 2 últimas expresiones. Cada elemento de arr apunta a un array de tamaño 1 (como si fuese una fila de una matriz con 1 sola columna, la de índice 0).

Page 84: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Ejercicio 8, probar, analizar y mejorar!

Page 85: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Ejercicio 8, probar, analizar y mejorar!

Page 86: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Ejercicio 8, probar, analizar y mejorar!

http://ascii.cl/es/

Page 87: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices

• Este tipo de arrays (array de array) deben mapearse al espacio de direcciones unidimensional de la memoria principal

• int matrix[2][3]={{1,2,3},{4,5,6}};

Page 88: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices

• Cada fila de una matriz es un array, por eso es un array de arrays

Page 89: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Uso de sizeof con una matriz

Page 90: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices

Page 91: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices y punteros • Si se desea acceder al 2º elemento, usando la

notación de punteros y el nombre de la matriz printf("%p\n", matrix);

//imprime 100 en el ejemplo dibujado

printf("%p\n", matrix +1);//imprime 120

• al ejecutar este código puede apreciarse que, la dirección retornada por matrix+1, no tiene un desplazamiento u offset de 4 bytes con respecto al comienzo del array!! sino, es el correspondiente a toda la primera fila, por tanto se tiene un offset de 20 bytes (5*4 bytes). Como una matriz es considerada un array de arrays, en realidad nos devuelve la dirección del 5º elemento, de índices [1] [0](el que contiene un 6). Esto puede corroborarse imprimiendo:

printf("%d\n",sizeof(matrix[0]));

Page 92: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices y punteros • Si se necesita acceder al segundo elemento (el que

contiene 2) debemos añadir 1 (número de la columna del 2º elemento) a la fila 0 (fila del segundo elemento):

printf("%d\n", *(matrix[0] + 1));

//notación combinada índices y offsets

• matrix[0] retorna la dirección del primer elemento (elemento 0) de la primer fila (fila 0), la cual es una dirección de un array de enteros. Ahora, añadir 1 implica añadir el tamaño de un entero (desplazarse 4 bytes)

printf("%p %d\n", matrix[0] + 1, *(matrix[0] + 1));

Page 93: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices dinámicas

• Cuando la matriz se declara: int matrix[2][5] = {{1, 2, 3, 4, 5},{6, 7, 8, 9, 10}};

• Se asignan espacios contiguos en memoria (como si fuese un vector de 10 elementos)

• Sin embargo, al usar malloc para asignar memoria dinámicamente correspondiente a una matriz, hay variantes en la forma en que es alojada en memoria. Puesto que un array multidimensional puede tratarse como un “array de array”, no hay razón para que el array “interno” (las columnas de las distintas filas) ocupen espacios contiguos. Cuando se utilizan índices para recorrer tal array, la naturaleza “no contigua” del mismo es transparente para el programador.

Page 94: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices dinámicas

• Una forma de reservar memoria dinámicamente para una matriz donde no hay garantía de que los elementos de la matriz ocupen posiciones contiguas: en primer lugar se reserva espacio para el array “externo” (filas) y luego se reserva espacio para los elementos de cada fila usando sentencias malloc separadas:

Page 95: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices dinámicas

• Al usar malloc separados no se garantiza la contigüidad de la memoria, depende del gestor del heap.

int rows = 2;

int columns = 5,i;

int **matrix = (int **) malloc(rows * sizeof(int *));

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

matrix[i] = (int *) malloc(columns * sizeof(int)); }//ahora puedo usar la notación con 2 índices

Page 96: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices dinámicas

Page 97: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Matrices dinámicas

• Para liberar la memoria asignada dinámicamente lo realizo en orden inverso! al que utilicé para reservar memoria, 1º libero el espacio reservado para las columnas de cada fila y luego el reservado para el array delas filas (el “externo):

for(i=0;i<rows;i++)

free(matrix[i]);

free(matrix);

Page 98: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Otras posibilidades

• Usar posiciones contiguas y aritmética de punteros. En este caso la memoria para la matriz se asigna en una única operación int *matrix = (int *)malloc(rows * columns *

sizeof(int));

Page 99: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Otras posibilidades

• Luego cuando el array es desreferenciado no pueden usarse los dos índices, en lugar de ello los índices deben calcularse manualmente índices (se perdió información acerca de la forma de la matriz, necesaria por el compilador para poder permitir doble índices) for (i = 0; i < rows; i++) {

for (j = 0; j < columns; j++) {

*(matrix + (i*columns) + j) = i*j;

} }

• Este enfoque tiene una aplicación limitada en el mundo real pero, sirve para ilustrar la relación entre una matriz (array de 2 dimensiones) y la naturaleza unidimensional o lineal de la memoria

Page 100: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Otras posibilidades

• La 2º técnica asigna en primer lugar espacio en memoria para el array “externo” (filas) , como un array de punteros a enteros y luego asigna memoria en un bloque de espacios contiguos para todos los elementos de dichas filas

• El primer malloc asigna espacio de memoria para un array de punteros a enteros, cada uno de ellos apuntando a una fila, en el ejemplo dibujado, este bloque está alojado a partir de la dirección 500:

Page 101: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Otras posibilidades

int rows = 2;

int columns = 5,i;

int **matrix = (int **) malloc(rows *

sizeof(int *));//ídem a la 1º técnica

Page 102: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Otras posibilidades

• El segundo malloc asigna espacio de memoria a partir de una dirección del heap determinada (600 en el dibujo), para los 10 elementos de la matriz. En el siguiente lazo for, a cada elemento del primer array, se le asigna una porción de la memoria reservada dinámicamente por el segundo malloc

Page 103: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Otras posibilidades

int rows = 2;

int columns = 5;

int **matrix = (int **) malloc(rows * sizeof(int *));

matrix[0] = (int *) malloc(rows * columns * sizeof(int));

for (int i = 1; i < rows; i++)

matrix[i] = matrix[0] + i * columns;

Nota: Estas 3 técnicas le servirán para resolver parte del ejercicio 10

Page 104: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y 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 2 elementos desordenados con una función:

Page 105: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones

Page 106: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y 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 invocante pase punteros a los valores que se intercambian (o sea copias de las direcciones de memoria de variables del mismo tipo que el puntero)

Page 107: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones

Page 108: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones

• Aplicaciones: poder devolver más de un valor

int edad;

double altura;

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

Page 109: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones #include <stdio.h> void conversor(int*h, int*m, int*s); int 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); return 0; } 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 110: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones

• Cuando un nombre de un arreglo se pasa a una función lo que se pasa es la dirección del elemento inicial (índice 0)

• 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

• En general, cuando se escriben funciones para manejo de strings se prefiere la notación de punteros, en lugar de char [ ]

Page 111: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones

Page 112: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros y funciones • Puesto que s es un puntero es perfectamente legal incrementarlo;

s++ no tiene efecto alguno sobre la cadena de caracteres pasada como argumento real a strlen, sólo incrementa la copia privada del puntero de strlen

• Llamadas como estas, funcionan: – strlen(“hola mundo”);//constante de cadena

– char simpleArray[] = "simple string"; strlen

(simpleArray);

– char *simplePtr =

char*)malloc(strlen("simple string")+1);

strcpy(simplePtr, "simple string");

printf("%d\n",stringLength(simplePtr)); //más explícito que con char []

Page 113: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Paso de argumento puntero a constante

• El paso de argumentos punteros a constante es una técnica común en C

• Por eficiencia en el uso de memoria utilizo un argumento de tipo puntero, pásandole la dirección de un dato, pero si no deseo que la función modifique dicho dato, a dicho argumento lo declaro como puntero a constante

Page 114: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Paso de argumento puntero a constante

• Muy común en las funciones declaradas en string.h

– int strcmp(const char *s1, const

char *s2);

Page 115: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Retornar un puntero

– Asignar memoria dinámicamente (por ejemplo, con malloc) dentro de la función y retornar la dirección de comienzo del bloque de memoria asignado a través del puntero que retorna la función (malloc, realloc o calloc). El invocante de dicha función es responsable de liberar ese bloque de memoria cuando no lo necesite más

– O, pasar un objeto a través de un puntero como argumento de la función que lo modifica. El invocante es responsable de asignación y liberación de memoria dinámica

Page 116: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Retornar un puntero #include <stdio.h>

#include <stdlib.h>//necesaria para malloc

int* allocateArray(int size, int value) {

int i;

int* arr = (int*)malloc(size * sizeof(int));

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

arr[i] = value;

}

return arr;}

void main(){

int i;

int* vector = allocateArray(5,45);

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

printf("%d\n", vector[i]);

}

free(vector);

}

Page 117: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Retornar un puntero #include <stdio.h> #include <stdlib.h> void allocateArray(int *arr, int size, int value) { int i; if(arr != NULL) { for(i=0; i<size; i++) { //si el puntero es NULL no se ejecuta ninguna //acción y el programa no termina anormalmente al invocar la función arr[i] = value; }}} int main(){ int* vector = (int*)malloc(5 * sizeof(int)); int i; //modifico contenido de vector, ahora tiene “basura” allocateArray(vector,5,45); for(i=0; i<5; i++) { printf("%d\n", vector[i]); } free(vector); return 0;}

Page 118: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Retornar un puntero

• Importante: Nunca se debe retornar un puntero a una variable local. Este es un error muy común, cometido principalmente por no comprender cómo trabaja el stack de programa. Una vez que la función retorna al punto donde se la invocó, la dirección de memoria retornada (de la variable local) ya no es válida puesto que, el stack frame dicha función es extraído del stack

Page 119: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar un string a inicializar #include <stdio.h> #include <stdlib.h> #include <string.h> char* format(char *buffer, const char* name, int quantity, int weight){ char *formatString = "Item: %s Quantity: %u Weight: %u"; int formatStringLength = strlen(formatString)-6; int nameLength = strlen(name); int length = formatStringLength + nameLength +10 + 10 + 1; //10 y 10 ancho cantidad y peso +1 terminador if(buffer == NULL) //sino paso un buffer creado con malloc buffer = (char*)malloc(length);//si buffer NULL reservo sprintf(buffer,formatString,name, quantity, weight); return buffer;} int main(){ //paso un buffer suponiendo una longitud máxima para el string char *b=(char*)malloc(80); //no proveo el buffer o dejo que la funcione calcule long.string char *vacio=NULL; //main responsable de asignar memoria y liberar printf("%s\n",format(b,"Axle",25,45)); //liberar b printf("%s\n",format(vacio,"Axle",25,45)); //liberar vacio, no olvidar o puedo tener fugas de memoria return 0;}

Page 120: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar puntero a puntero • En el último ejemplo a allocateArray se pasaba como 1º

argumento un puntero devuelto por malloc que apuntaba un array que contenía basura, luego de la invocación que se hace en main dicho array queda lleno con 5 nros. 45

• En C el paso de argumentos es siempre por valor, aún cuando se pasa como argumento un puntero. Si se desea modificar el puntero original y no su copia, debe pasarse como puntero a puntero. En el siguiente ejemplo se pasa a la función allocateArray un argumento que es un puntero a un array de enteros (en este ejemplo un puntero inicialmente con valor NULL); la función asigna memoria dinámicamente para dicho array y lo inicializa. A través de este argumento la función retornará la dirección de comienzo de la memoria asignada dinámicamente e inicializada

• Se suele usar esto para funciones de manejos de estructuras dinámicas tales como las listas enlazadas

Page 121: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar puntero a puntero #include <stdio.h>

#include <stdlib.h>//necesaria para malloc

void allocateArray(int **arr, int size, int value) {

int i;

*arr = (int*)malloc(size * sizeof(int));

if(*arr != NULL) {

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

*(*arr+i) = value;

}}}

void main(){

int *vector = NULL;

int i;

allocateArray(&vector,5,45);

//paso la dirección de un puntero a entero

//puesto que el argumento es un puntero a puntero a entero

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

printf("%d\n", vector[i]);//ya no es NULL }

free(vector);}

Page 122: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar puntero a puntero

• Un ejemplo de organización de la memoria antes y después de la invocación a allocateArray: (este tipo de diagramas ayuda a identificar problemas tal como fugas de memoria)

Page 123: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar una matriz a una función

• Cuando se pasa un array como argumento a una función, se pasa un puntero al primer elemento de dicho array void foo(int array[][10]);

void foo(int array[10][10]);

• En el caso de una matriz (array de arrays) ¿qué tipo de punteros se le pasa?

• El primer elemento de una matriz es un array que se pasa a la función como un puntero a un array

Page 124: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar una matriz a una función

• La declaración: – int (*a)[10] ;

– Los () son obligatorios sino sería un array de 10 punteros a enteros

• Indica que a es un puntero a un array de 10 enteros (podría usarlo para matrices de enteros con filas que tienen 10 columnas)

– void foo(int (*array)[10]);

Page 125: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Pasar una matriz a una función

• Si se pasa a una función una matriz creada como array multidimensional:

int a2[5][7];

func(a2);

• No puede declarar la función con un argumento de tipo puntero a puntero (es un array de punteros (posiblemente a arrays de 1 dimensión), no están ubicados contiguos

• func(int **a) {…} /* incorrecto */

Page 126: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

#include <stdio.h> //http://cs-fundamentals.com/c-programming/arrays-in-c.php #define ROWS 4 #define COLS 3 void array_of_arrays_ver(int arr[][COLS]); void ptr_to_array_ver(int (*arr)[COLS]); int main () { int matrix[ROWS][COLS] = {{1, 2, 3},{4, 5, 6},{7, 8, 9},{10, 11, 12}}; printf("Printing Array Elements by Array of Arrays Version Function: \n"); array_of_arrays_ver(matrix); printf("Printing Array Elements by Pointer to Array Version Function: \n"); ptr_to_array_ver(matrix); return 0; }

Page 127: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

void array_of_arrays_ver(int arr[][COLS]){ int i, j; for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { printf("%d\t", arr[i][j]); } printf("\n"); }} void ptr_to_array_ver(int (*arr)[COLS]){ int i, j; for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { printf("%d\t", (*arr)[j]);//recorre columnas de una fila } arr++;//se mueve una fila printf("\n"); } }

Page 128: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

typedef

• C proporciona una facilidad llamada typedef para dar un nombre nuevo a cualquier tipo de datos (sinónimo)

• Por ejemplo, la declaración: – typedef int Longitud;

• hace del nombre Longitud un sinónimo de int. El tipo Longitud puede emplearse en declaraciones, casts, etc., exactamente de la misma manera en que lo podría hacer int. Longitud len, maxlen;

Longitud *lengths[];

Page 129: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

typedef

• De modo semejante, la declaración – typedef char *Cadena;

• hace a Cadena un sinónimo para char* o puntero a carácter, que puede usarse en declaraciones y casts: Cadena p, lineptr[MAXLINES],

alloc(int);

int strcmp(Cadena, Cadena);

p= (Cadena) malloc (100);

Page 130: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

typedef

• Nótese que el tipo que se declara en un typedef aparece en la posición de un nombre de variable, no justo después de la palabra typedef.

• Se debe destacar que una declaración typedef no crea un nuevo tipo en ningún sentido; simplemente agrega un nuevo nombre para algún tipo ya existente.

Page 131: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

typedef • Además de las razones puramente estéticas (y de

legibilidad), hay 2 razones principales para emplear typedef.

• La 1º es parametrizar un programa contra los problemas de portabilidad. Si se emplea typedef para tipos de datos que pueden ser dependientes de la máquina, cuando un programa se traslada, sólo los typedef requieren de cambios. Una situación común es usar nombres de typedef para varias cantidades enteras y, entonces hacer un conjunto apropiado de selecciones de short, int y long para cada máquina. Tipos como size_t de la biblioteca estándar son ejemplos.

Page 132: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

typedef

• El segundo propósito de typedef es proporcionar mejor documentación para un programa –un tipo llamado Treeptr puede ser más fácil de entender que uno declarado sólo como un puntero a una estructura complicada, como puede ser un nodo de un árbol binario.

Page 133: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones • Son punteros que almacenan direcciones de

funciones.

• Permiten técnicas de programación extremadamente interesantes, eficientes y elegantes. Proveen una forma de elegir en tiempo ejecución cuál función invocar (entre varias alternativas) sin usar sentencias de control tipo switch/if como así también pasar funciones como argumentos de otras (callback)

Page 134: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones

• La sintaxis para declarar un puntero a función puede resultar un poco confusa a primera vista (se parece al prototipo de una función), el uso del 1º par de paréntesis indica claramente que el * está ligado al nombre de la función y no al tipo de retorno: void (*foo)();

/*puntero a función que no toma

argumentos y no retorna ningún valor*/

Page 135: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones

• Importante: Por definición y tal como ocurre con los nombres de los arrays, cuando se usa el nombre de una función por sí misma, retorna la dirección de la misma:

• Veamos un ejemplo de uso de punteros a funciones:

Page 136: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones #include <stdio.h>

int (*fptr1)(int);/*puntero a función que toma como

argumento un entero y retorna un entero*/

int square(int num) {

return num*num;

}

void main()

{

int n = 5;

fptr1 = square; //fptr1=&square; es redundante

printf("%d squared is %d\n",n, fptr1(n));

//forma corta de invocación, ídem (*fptr1)(n)

}

Page 137: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones

• Por ser complicada la declaración de punteros a funciones, es conveniente el uso de typedef:

– typedef int (*funcptr)(int);

• Ahora puedo utilizar: funcptr fptr2;

fptr2 = square;

printf("%d squared is %d\n",n,

fptr2(n));

Page 138: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones

• El paso como argumento de un puntero a función es muy simple; mediante un ejemplo puede verse cómo el código resulta más flexible si se usa punteros a funciones. Aunque en este ejemplo se decide en tiempo de compilación a qué función llamar desde main, usando punteros a funciones esto puede decidirse en tiempo de ejecución:

Page 139: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Punteros a funciones #include <stdio.h>

int add(int num1, int num2) {

return num1 + num2;

}

int subtract(int num1, int num2) {

return num1 - num2;

}

typedef int (*fptrOperation)(int,int);

int compute(fptrOperation operation, int num1, int num2) {

return operation(num1, num2); //retorno un entero

}

void main(){

printf("%d\n",compute(add,5,6));

printf("%d\n",compute(subtract,5,6));

}

Page 140: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Retornar un puntero a función

#include <stdio.h>

int add(int num1, int num2) {

return num1 + num2;

}

int subtract(int num1, int num2) {

return num1 - num2;

}

typedef int (*fptrOperation)(int,int);

int compute(fptrOperation operation, int num1, int num2) {

return operation(num1, num2);

}

Page 141: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Retornar un puntero a función fptrOperation select(char opcode) {//retorno un puntero a función

switch(opcode) {

case '+': return add;

case '-': return subtract;

}

}

int evaluate(char opcode, int num1, int num2) {

fptrOperation operation = select(opcode);

return operation(num1, num2); //ídem que en compute

}

void main()

{

printf("%d\n",evaluate('+', 5, 6));

printf("%d\n",evaluate('-', 5, 6));

}

Page 142: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros a función

• Además pueden usarse arrays de punteros a funciones, a fin de poder seleccionar la función a evaluar en base a algún criterio.

• La declaración de un array de punteros a funciones es directa: – typedef int (*operation)(int, int);/*defino

tipo del array de punteros a funciones*/

operation operations[128] = {NULL};

/*inicializo cada elemento del array con punteros

a NULL*/

Page 143: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros a función

• Alternativamente podría declarar el array de punteros a funciones sin usar typedef: int (*operations[128])(int, int) = {NULL};

• La idea de este array de 128 elementos (correspondiente a los primeros 128 caracteres ASCII) es usar como índice un caracter (se pueden usar literales de tipo char puesto que son considerados como enteros en las operaciones) para seleccionar una función determinada a ejecutar. Por ejemplo: el ‘*’ indicará que quiero ejecutar una función de multiplicación, si existe.

Page 144: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros a función #include <stdio.h>

typedef int (*fptrOperation)(int,int);

fptrOperation operations[128] = {NULL};

int add(int num1, int num2) {

return num1 + num2;

}

int subtract(int num1, int num2) {

return num1 - num2;

}

void initializeOperationsArray() {/*array inicialmente con todos los

elementos igual a NULL*/

operations['+'] = add;

operations['-'] = subtract;}

Page 145: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Arrays de punteros a función int evaluateArray(char opcode, int num1, int num2) {

fptrOperation operation;

operation = operations[opcode];

/*en lugar de usar la función select para seleccionar una operación

aritmética a ejecutar*/

return operation(num1, num2);

/*debería chequear que operation sea !=NULL */

}

void main()

{

initializeOperationsArray();

printf("%d\n",evaluateArray('+', 5, 6));

printf("%d\n",evaluateArray('-', 5, 6));

}

Page 146: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Operaciones con punteros a funciones

• Los punteros a función, como otros punteros, pueden compararse con los operadores de igualdad o desigualdad

fptrOperation fptr1 = add;

if(fptr1 == add) {

printf("fptr1 points to add function\n");

}

else {

printf("fptr1 does not point to add

function\n");

}

Page 147: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Funciones callback

• En la librería stdlib existe qsort cuya signatura es:

void qsort(void *base, size_t nmemb, size_t tamanyo,

int (*comparar)(const void *, const void *));

• y que ordena un array que tiene una longitud igual a nmemb. El elemento

inicial es apuntado por base. El tamaño de cada elemento del array está especificado por tamanyo. El contenido del array es ordenado en orden ascendente, según una función de comparación apuntada por comparar, la cual es llamada con dos argumentos que apuntan a los objetos a ser comparados. La función retornará un entero menor, igual, o mayor que cero si el primer objeto es considerado, respectivamente a ser menor, igual, o mayor que el segundo. Si los dos elementos son iguales, su orden en el array ordenado no está definido.

• Para que sea genérica, el puntero a función es a una función que toma como argumento dos punteros a void

Page 148: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Funciones callback

• En el siguiente ejemplo dentro de una función sort, para ordenar los elementos de un array (en forma ascendente, descendente o según algún otro criterio) hay que compararlos de a dos y, ver si se necesita hacer un intercambio en el orden de dichos elementos (swap). La función de ordenamiento (sort) resulta más flexible si se le pasa como argumento una función de comparación; utilizando distintas funciones de comparación, se permite realizar ordenamientos de distintas formas sin tener que escribir varias funciones de ordenamiento.

Page 149: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Funciones callback #include <stdlib.h>

#include <ctype.h> //para tolower

typedef int (fptrOperation)(const char*, const char*);

//puntero a función

int compare(const char* s1, const char* s2) {

return strcmp(s1,s2);

}

//escribe los caracteres en minúscula

char* stringToLower(const char* string) {

char *tmp = (char*) malloc(strlen(string) + 1);

char *start = tmp;

while (*string != 0) {

*tmp++ = tolower(*string++);

}

*tmp = 0;

return start;

}

Page 150: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

int compareIgnoreCase(const char* s1, const char* s2) {

char* t1 = stringToLower(s1);

char* t2 = stringToLower(s2);

int result = strcmp(t1, t2);

free(t1);

free(t2);

return result;}

//funcion de ordenamiento basado en el método de la burbuja

//paso la dirección del array (la comparación espera punteros a char), el

//tamaño y el puntero a función de comparación

void sort(char *array[], int size, fptrOperation operation) {

int swap = 1, i;

char *tmp;

while(swap) {

swap = 0;

for(i=0; i<size-1; i++) {

//determino si debo hacer un swap o no entre los 2 elementos comparados

if(operation(array[i],array[i+1]) > 0){

swap = 1;

tmp= array[i];

array[i] = array[i+1];

array[i+1] = tmp;}}}}

Page 151: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

void displayNames(char* names[], int size) {

int i;

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

printf("%s ",names[i]);

}

printf("\n");

}

void main(){

char* names[] = {"Bob", "Ted", "Carol", "Alice", "alice"};

sort(names,5,compare);

displayNames(names,5);

sort(names,5,compareIgnoreCase);

displayNames(names,5);

}

Page 152: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Expresiones con punteros

Page 153: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Expresiones con punteros • Para leer expresiones complejas con punteros se usa

una regla llamada derecha-izquierda (https://www.codeproject.com/articles/7042/how-to-interpret-complex-c-c-declarations). Consiste en leer una expresión desde los paréntesis más internos de la misma yendo hacia la derecha y luego a la izquierda; el cambio de dirección se debe producir cuando se encuentra un paréntesis, se continúa así hasta que se lee toda la expresión

• Un pequeño cambio a esta regla: para comenzar a leer la expresión se lo hace desde el nombre de la variable y no desde los paréntesis más internos de la expresión

Page 154: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Expresiones con punteros

Page 155: Punteros · John Von Neumann • 1903-1957 • Matemático • Publicó la idea de programa almacenado en memoria (1945) Lineamientos del Modelo de Von Neumann • Los datos y programas

Expresiones con punteros