Punteros y arreglos
Transcripción
Punteros y arreglos
Programación científica Punteros y arreglos Dra. Elisa Schaeffer [email protected] PISIS / FIME / UANL Punteros y arreglos– p. 1 Arreglo Un arreglo es un conjunto de una cantidad fija de variables del mismo tipo que se maneja por el mismo nombre a través de ı́ndices: int elementos[5]; /* ANSI-C */ int i = 3; int[] elementos = new int[i]; /* Java */ elementos[i] = 4; Los índices comienzan de cero y terminan en n − 1 donde n es el número total de elementos. Punteros y arreglos– p. 2 Cayendo afuera: ANSI-C #include <stdio.c> int main(int argc, char** args) { int data[5]; data[5] = 3; printf("Done.\n"); return 1; } Punteros y arreglos– p. 3 Reacciones variadas @ubuntu$ gcc errores.c @ubuntu$ ./a.out Done. Bus error (core dumped) @ubuntu$ @yalma$ gcc errores.c @yalma$ ./a.out Done. @yalma$ Punteros y arreglos– p. 4 Cayendo afuera en Java public class Errores { public static void main(String[] args) { int[] data = new int[5]; data[5] = 3; System.out.println("Done."); return; } } Punteros y arreglos– p. 5 Reacción consistente $ java Errores Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Errores.main(Errores.java:4) $ Punteros y arreglos– p. 6 Arreglos multidimensionales int multi[3][4]; int a, b; for (a = 0; a < 3; a++) { for (b = 0; b < 4; b++) { multi[a][b] = rand() % 7; } } for (a = 0; a < 3; a++) { for (b = 0; b < 4; b++) { printf(" %d", multi[a][b]); } printf("\n"); } Punteros y arreglos– p. 7 Puntero En C, para crear arreglos sacando la capacidad de una variable, se necesita punteros. Un puntero es una variable que contiene la otra variable en la memoria. dirección a Los punteros son unas maravillas sin los cuales uno lo logra nada útil en ANSI-C en el largo plazo. Punteros y arreglos– p. 8 Definición de punteros #include <stdio.h> int main(int argc, char** args) { char* puntero_a_char; int* puntero_a_int; char a = ’a’; int b = 7; puntero_a_char = &a; puntero_a_int = &b; printf("%c %d\n", *puntero_a_char, *puntero_a_int); return 1; } Punteros y arreglos– p. 9 Notación *t &a *b = puntero a una variable de tipo t = dirección de la variable a = valor apuntado por el puntero b El compilador queja siempre y cuando uno usa mal esta notación. Punteros y arreglos– p. 10 Tamaño de tipo Al reservar memoria, vamos a recibir un puntero a la región reservada. Al reservar, vamos a necesitar saber cuánto espacio reservar. La función sizeof(tipo) devuelve un entero que indica cuántos bytes necesita una variable del tipo definido. La salida de sizeof() es de tipo size_t que es simplemente un entero constante sin signo. El espacio necesario para k variables se calcula por multiplicar: por ejemplo k*sizeof(int), donde k puede ser constante o variable. Punteros y arreglos– p. 11 sizeof() #include <stdio.h> int main(int argc, char** args) { size_t charsize = sizeof(char); size_t intsize = sizeof(int); size_t longsize = sizeof(long); size_t floatsize = sizeof(float); size_t doublesize = sizeof(double); printf("char %d, int %d, long %d, float %d, double %d\n", charsize, intsize, longsize, floatsize, doublesize); return 1; } Salida: char 1, int 4, long 4, float 4, double 8 Punteros y arreglos– p. 12 Reservación de memoria void* malloc(size_t n) = reservar n bytes de memoria void* cealloc(size_t n) = reservar e inicializar a cero void* realloc(void* p, size_t n) = aumentar la región free(void* p) = liberar el espacio apuntado por el puntero Punteros y arreglos– p. 13 Conversión de void Las salidas son tipo void . Para asignar la salida de malloc() a un int ∗, por ejemplo, hay que hacer conversión explícita (inglés: type casting): int* d = (int*)malloc(7*sizeof(int)); m/c/realloc da la salida NULL si la operación no es éxitosa. Es importante verificar esto en cada programa. Son de la librería stdlib.h . Punteros y arreglos– p. 14 Punteros a punteros #include <stdio.h> #include <stdlib.h> int main(int argc, char** args) { int i, j, h, k = 4; int*** tresd = (int***)malloc(sizeof(int**)*k); for (i = 0; i < k; i++) { tresd[i] = (int**)malloc(sizeof(int*)*(k-1)); for (j = 0; j < k - 1; j++) { tresd[i][j] = (int*)malloc(sizeof(int)*(k-2)); for (h = 0; h < k - 2; h++) { tresd[i][j][h] = rand() % 10; } } } return 1; } Punteros y arreglos– p. 15 ¿Resultado? Lo que imprime el programa anterior: 1 6 8 3 2 0 7 7 7 6 9 5 0 2 2 9 9 6 0 2 3 1 2 2 Nota: falta verificar el resultado de malloc() Punteros y arreglos– p. 16 string.h char* strcpy(char*, char*) copiar el segundo al primero char* strcat(char*, char*) juntar dos en uno int strcmp(char*, char*) La librería string.h permite realizar varias operaciones con arreglos de char o punteros a char . La lista muestra una pequeñ parte. comparar (antes, igual, después) char* strchr(char*, int) la primera ocurrencia de un símbolo char* strstr(char*, char*) primera ocurrencia de otra cadena size_t strlen(char*) largo (número de símbolos “ocupados”) Punteros y arreglos– p. 17 Puntero a función Funciones que dan el mismo tipo de salida y toman los mismos tipos de parámetros se puede manejar a través de un puntero de ese “prototipo”: double multiply(int a, double b) { printf("%.4f\n", b*a); return b*a; } typedef double (*funpoint)(int, double); Punteros y arreglos– p. 18 Uso de punteros a funciones Tres maneras de llamar la misma función: funpoint fp = &multiply; multiply(3, 1.2); (*fp)(3, 1.2); fp(3, 1.2); Punteros y arreglos– p. 19 Función como parámetro #include <stdio.h> // printf() #include <stdlib.h> // RAND\_MAX ... // lo de la dispositiva anterior void task(funpoint f) { int first = rand() % 7; double second = (rand()*1.0)/RAND\_MAX; f(first, second); return; } int main(int argc, char** args) { funpoint fp = &multiply; task(fp); return 1; } Punteros y arreglos– p. 20