Algoritmos y Lenguaje de Programación, Sección 1
Punteros
Uso avanzado de punteros
• Contienen direcciones de memoria )Punteros a tipos de datos simples int, char, float, double
Mario Medina C.
[email protected]
Declaraciones simples int f; int *f; int* f, g; entero */ int f(); entero */ int *f(); puntero a
/* entero */ /* puntero a entero */ /* f es puntero, g es /* funcion que retorna /* funcion que retorna entero */
Declaraciones complejas int (*f)[]; /* puntero a un vector de enteros */ int (*f[])(); /* vector de punteros a funciones que retornan enteros */ int *(*f[])(); /* vector de punteros a funciones que retornan punteros a enteros */
©Mario Medina C.
)Punteros a estructuras )Punteros a vectores y matrices )Punteros a punteros
Declaraciones complejas int (*f)(); /* puntero a funcion que retorna un entero */ int *(*f)(); /* puntero a funcion que retorna un puntero a entero */ int f[]; /* vector de enteros */ int *f[]; /* vector de punteros a enteros */
cdecl • Programa que interpreta declaraciones complejas )Ejecutable de línea de comando en Windows cdecl.exe cdecl> explain int (*(*f)())[10] Declare f as pointer to function returning pointer to array 10 of int
1
Algoritmos y Lenguaje de Programación, Sección 1
Punteros a funciones • Función es código residente en memoria )Posee una dirección en memoria )Puntero puede apuntar a función
• Usos típicos )Tablas de salto (jump tables) )Paso de funciones como argumentos (callback functions)
Punteros a funciones int g = g = g =
g; f(25); (*pf)(25); pf(25);
• Todos son métodos equivalentes de invocar a la función f() de la transparencia anterior
Tablas de salto double double double double
add(double, sub(double, mul(double, div(double,
int f(int); /* Funcion que recibe entero */ int (*pf)(int) = &f; /* Puntero a función anterior */
• Signo & es opcional )C convierte nombre de una función a un puntero a dicha función
Tablas de salto switch (oper){ case ADD: result = add(op1, case SUB: result = sub(op1, case MULT: result = mul(op1, case DIV: result = div(op1, }
op2); break; op2); break; op2); break; op2); break;
Tablas de salto double); double); double); double);
double (*oper_func[])(double, double) = {add, sub, mul, div};
©Mario Medina C.
Punteros a funciones
• oper_func() es un vector de punteros a funciones • switch() puede ser reemplazado por result = oper_func[oper](op1, op2); )Esto sólo funciona si ADD, SUB, MULT, DIV son enteros sucesivos comenzando en 0
2
Algoritmos y Lenguaje de Programación, Sección 1
Funciones de Callback Nodo *busca(Nodo *nodo, int const valor) { while (nodo != NULL) { if (nodo->dato == valor) break; nodo = nodo->proximo; } return nodo; }
Funciones de Callback • Solución: escribir una función que reciba como argumentos: )Un puntero al valor a comparar, y )Una función de comparación
• Función de comparación )Recibe punteros a operandos como argumentos ` Punteros a void (tipo de datos desconocido)
)Retorna 0 si operandos son iguales
Funciones de Callback int comparaInts(void const *a, void const *b) { if (*(int *) a == *(int *) b) return 0; else return 1; }
Funciones de Callback • Función anterior busca un valor entero en una lista encadenada )Funciona sólo para lista de enteros
• Cómo buscar en una lista de números de punto flotante? )Escribir otra función, pero que reciba un float como argumento
Funciones de Callback Nodo *busca(Nodo *nodo, void const *valor, int (*compara)(void const *, void const *) { while (nodo != NULL) { if (compara(&nodo->dato, valor) == 0) break; nodo = nodo->proximo; } return nodo; }
Funciones de Callback • Cómo se usa para buscar enteros? resultado = busca(raiz, &valorInt, comparaInts);
• Cómo se usa para buscar ristras? resultado = busca(raiz, “ristra”, strcmp); )Función busca() es ahora una función aplicable a diferentes tipos ` Función de comparación diferente para cada tipo
©Mario Medina C.
3
Algoritmos y Lenguaje de Programación, Sección 1
Argumentos de línea de comandos • Función main() sólo puede tener argumentos )void )int argc, char **argv
• Argc: cuenta argumentos del comando • Argv: puntero a vector de ristras )Puede escribirse como int argc, char *argv[]
Vector argv • Vector de punteros a caracteres )Terminado por un NULL )Primer elemento es siempre el nombre del programa ejecutado
• Para imprimir sólo los argumentos while (*++argv != NULL) { printf(“%s\n”, *argv); }
argc y argv • gcc prog1.c prog2.c –o prog.exe argc 5
g c c \0
argv
p r o g 1 . c \0 p r o g 2 . c \0 \0
- o \0 p r o g . e x e \0
Usando argv int main(int argc, char *argv[]) { int i, j; for (i = 0; i < argc; i++) { printf("argv[%d] = %s\n", i, argv[i]); for (j = 0; argv[i][j]; j++) printf ("argv[%d][%d] is %c\n", i, j, argv[i][j]); } return(0); }
Ristras constantes
Punteros a ristras constantes
• Cómo se manipulan las ristras constantes en una expresión?
• Operaciones sobre ristras constantes
)Compilador almacena los caracteres en alguna región de memoria )Expresión equivalente a un puntero a una ristra )Cómo se evalúa “hola” + 1 ? )“hola” equivale a un puntero a caracter
)Cómo se evalúa *”hola” ? ` Indirección aplicada a puntero a caracter ` Devuelve el objeto apuntado (el caracter ‘h’)
)Cómo se evalúa ”hola”[3] ? ` Equivalencia entre punteros y vectores ` Devuelve el 4to. elemento del vector (el caracter ‘a’)
` Aritmética de punteros
)“hola” + 1 es un puntero a ‘o’
©Mario Medina C.
4
Algoritmos y Lenguaje de Programación, Sección 1
Ejemplo void binToASCII(unsigned int valor) { unsigned int cuociente; cuociente = valor/10; if (cuociente != 0) binToASCII(cuociente); putchar(valor%10 + ‘0’); }
Ejemplo void binToASCII(unsigned int valor) { putchar(“0123456789ABCDEF”[valor%16]); }
• Versión no recursiva )Usa el argumento módulo 16 como un índice al vector formado por los 10 dígitos y 6 letras del código hexadecimal
• Versión recursiva
Ejercicio void histograma(int valor) { n += 5; n /= 10; printf(“%s\n”, “**********” + 10 – n); }
• Cómo funciona este programa? )Pruébelo para distintos valores enteros de entrada entre 0 - 100
©Mario Medina C.
5