Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de...

62
Punteros

Transcript of Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de...

Page 1: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros

Page 2: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros

• 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 al paso de argumentos – Por referencia con argumentos tipo punteros

– 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 3: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 que se pase como argumento real

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

Page 4: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

Page 5: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

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

• La forma de obtener los resultados deseados: 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 6: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

Page 7: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

• Aplicaciones: poder devolver más de un valor • int scanf(const char *formato, arg1, arg2, …, argn);

int edad;

double altura;

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

• Sirven para pasar punteros a objetos de datos grandes, evitando la sobrecarga de pasar una copia de los objetos mediante llamadas por valor.

Page 8: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

• En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como información una x cantidad de segundos, desglose esa cantidad de segundos en las horas, minutos y segundos que contiene. Mostrar el resultado por pantalla

• Ejemplo de salida por pantalla: En 115400 segundos hay: 32 horas, 3 minutos y 20 segundos

• En el capítulo de estructuras (registros) veremos otra posibilidad de resolver este ejercicio

Page 9: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones #include <stdio.h> void conversor(int*h, int*m, int*s);//sin espacio para indentar int main(){ int segundos, minutos, horas, auxiliar; setbuf(stdout,0); 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 10: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

• Cuando se pasa a una función un argumento que es un nombre de un arreglo, 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 11: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones

Page 12: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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

• Prueben realizar un printf (“%s”) del string con el cual invocaron a strlen y, efectivamente verán el string que pasaron como argumento

Page 13: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y funciones • 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");

/* nunca use sizeof para determinar longitud de 1 string (*char)*/

-char command[16];

printf("Enter a Command: ");

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

mejor usar gets o más seguro fgets*/

strlen(command);

Page 14: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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, pasándole 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 15: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 16: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Retornar un puntero

– Existen 2 formas de hacerlo, la primera:

– Dentro del cuerpo de la función se asigna memoria dinámicamente (por ejemplo, con malloc) y se retorna 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 (free) cuando no lo necesite más

Page 17: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 de dicha función es extraído del stack

Page 18: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Retornar un puntero #include <stdio.h>

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

int* allocateArray(int size, int value) {

int i;//asigna memoria y llena con un valor

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

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

arr[i] = value; //notación índices

}

return arr;}

void main(){

int i;

int* vector = allocateArray(5,45);

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

printf("%d\n", vector[i]);//notación índices

}

free(vector);

}

Page 19: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Retornar un puntero

Page 20: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 21: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 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: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 23: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros y arrays

Page 24: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 25: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Retornar un puntero

• Segunda forma: 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 26: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Retornar un puntero #include <stdio.h> #include <stdlib.h> //al pasar un array como argumento hay que pasar la dimensión void fillArray(int *arr, int size, int value) { int i; if(arr != NULL) { for(i=0; i<size; i++) { //buena práctica: 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” fillArray(vector,5,45); for(i=0; i<5; i++) { printf("%d\n", vector[i]); } free(vector); return 0;}

Page 27: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Para el ejercicio 6

#include <stdio.h> #include <stdlib.h> //la librería estándar no tiene una función para invertir strings char* reverse(char *str) { int j, largo=strLargo(str),i; //reservar un byte mas para el terminador nulo char* reversed = (char*) malloc( largo + 1); for (i = largo - 1, j=0; i>=0; i--, j++) { reversed[j] = str[i]; } reversed[j + 1] = '\0'; //no olvidar añadir terminador nulo al final return reversed; }

Page 28: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Retornar la dirección de un literal

• Ver la solución propuesta al ejercicio 4 donde se pide escribir una función que tome como argumento un entero positivo entre 1 y 7 y retorne un puntero a cadena con el nombre del día de la semana correspondiente al argumento

• char *dia_de_la_semana( int d );

• Si invoco la función con el valor 6, debe devolver el string “sábado”

Page 29: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 7

• Escribir una función que reciba como argumento un entero y retorne una cadena de caracteres en su representación decimal.

• Ídem para: representación octal, hexadecimal y binaria (genere una función por cada una de estas opciones)

Page 30: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Conversiones de string

• La función sprintf realiza las mismas conversiones que printf, pero almacena la salida en una cadena, pasada como 1º argumento (debe ser lo suficientemente grande), en lugar de hacerlo en la salida estándar

• int sprintf(char *cadena, char

*format, argv arg2, ...)

• Puede usarse para enviar datos (por ejemplo de un sensor) a través de un puerto serie

Page 31: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

#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); return 0; }

Page 32: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Conversiones de string #include <stdio.h> #include <stdlib.h> //itoa no forma parte del estándar ANSI C int main() { char str[10]; /* MUST be big enough to hold all the characters of your number!! */ //el tercer argumento es la base (entre 2 y 36) 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 33: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 6

• El siguiente código está basado en la propuesta planteada en el libro de Kernighan & Ritchie Ítem 3.6, válido para representar números entre 2 y 35

• Extraído de: http://www.strudel.org.uk/itoa/, char* version 0.4

Page 34: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como
Page 35: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Arrays de punteros

• Puesto que en sí mismo los punteros son variables pueden almacenarse en arreglos tal como los otros tipos de variables

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

Page 36: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Arrays de punteros

• 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 37: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 38: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Arrays de punteros

Abcdefghi

xyz

Qwertyuiopasdfg

Abcdefghi

xyz

Qwertyuiopasdfg

Page 39: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Arrays de punteros

• Un ejemplo numérico de un vector de punteros estático donde cada elemento apunta a un único entero (inicializado con valores del 0 al 4). Ya veremos cómo crear arrays dinámicos de punteros int* arr[5]; int i; for(i=0; i<5; i++) { //creo espacio en el heap para el entero arr[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) //lleno con valores del 0 al 4 *arr[i] = i;

}

Page 40: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

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

Page 41: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

Page 42: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

Page 43: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 44: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

Page 45: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

Page 46: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 47: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

• arr es un array de punteros a enteros

• (arr+i) muestra la dirección donde está cada elemento de arr (como son punteros, las direcciones están separadas por 4 bytes)

• *(arr+i)=arr[i] muestra el contenido de cada elemento de arr que es un puntero, son direcciones de memoria devueltas por malloc

• **(arr+i)=* arr[i] son los enteros a los que apunta cada puntero del array arr[i]

Page 48: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Punteros a punteros

Page 49: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 8

• Se necesita contar las letras de un texto ingresado. El texto puede tener varias oraciones.

• Crear una rutina que almacene las letras y la cantidad de veces que aparecen.

• Generar un informe con el detalle, en caso de que no sean caracteres alfabéticos o númericos, mostrar su valor hexadecimal.

• Debe crear un vector de punteros que almacenen las frases y luego recorrerlo con un doble puntero.

Page 50: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 8

• Ejercicio extenso pero contiene muchas funciones de librería string

• Ver cómo se crea el array dinámico de punteros conteniendo frases, usando un puntero a puntero y malloc

• Investigar el uso de la función strtok de la librería string que sirve para separar strings en subcadenas delimitadas por determinados caracteres, por ejemplo extraer día mes y año de “12/10/1892” o, horas minutos y segundos de “23:34:20”, etc. Ver por ej.: https://parzibyte.me/blog/2018/11/13/separar-cadena-delimitadores-c-strtok/

Page 51: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 8, probar, analizar y mejorar!

Page 52: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 8, probar, analizar y mejorar!

Page 53: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Ejercicio 8, probar, analizar y mejorar!

Tabla de códigos ASCII: http://ascii.cl/es/

Page 54: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 55: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Matrices

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

Page 56: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Matrices

Page 57: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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. Veremos una, ver las demás en el apunte

• 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 58: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 (columnas) usando dos sentencias malloc separadas:

Page 59: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Matrices dinámicas

Page 60: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 61: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

Matrices dinámicas

Page 62: Punteros - dsi.fceia.unr.edu.ar · Punteros y funciones •En lugar de resolver ejercicio 5 de práctica 1, intente escribir una función void que, cuando la invoque, le pase como

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 de las filas:

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

free(matrix[i]);

free(matrix);