Uso avanzado de punteros

Anuncio
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
Descargar