Funciones

Anuncio
Funciones
Clase 9
Introducción a la Computación
Patricia Borensztejn
Definición de una función
• Esta función calcula el logaritmo en base b de
un número x
Tipo de retorno
Sentencias
Parámetros
Variables
Locales
Sentencia
return
Invocación de una función
• La definición de una función no hace que ésta se
ejecute. Salvo la función principal, main() (que es
invocada por el SO), todas las funciones han de
ser invocadas desde alguna función, que incluso
puede ser ella misma (recursivas).
parámetros reales
variable donde se guarda el
valor de retorno
identificador
Tipo de Retorno
• Toda función retorna un valor. Si no nos interesa el
valor de devolución de la función podemos hacer dos
cosas:
– Ignorarlo
– Declarar el tipo de retorno como tipo void.
int main()
{
saludos();
return 0;
}
Sentencia return
• La sentencia return termina la ejecución de la función,
aunque puede haber mas de una dentro del cuerpo de la
función, la primera que se ejecuta da fin a la función.
• Si no hay sentencia return en una función, este termina
con la última sentencia del cuerpo de la función.
Variables Locales
• Toda variable declarada dentro de la función se llama
local porque solo «vive» mientras la función está
activada (ejecutándose).
• Cuando la función finaliza, las variables locales
desaparecen de la memoria…
• ¿Como es eso? Porque cada activación de la función
utiliza una zona de memoria propia: allí se reserva
espacio para sus variables locales, para sus parámetros,
para su valor de retorno y también para la dirección de
retorno al programa que la invocó.
• Cuando termina la función, y antes de volver al
programa invocador, se libera toda la zona de memoria
usada por ella.
Variables Locales
Variables Globales
• El uso de las variables globales… genera confusión y
resta legibilidad a los programas. Como ventaja, se
ahorra el paso de parámetros.
Parámetros
• Una función puede NO tener parámetros: por
ejemplo, main().
• Otro ejemplo, rand() definida en stdlib.h
int main()
{
int i;
for (i=0; i<10; i++)
printf ("%d\n", rand() % 6 + 1 );
}
Parámetros
• Parámetros escalares: paso por valor
• En algunos lenguajes se llama
paso por copia, pues
efectivamente lo que sucede
en el momento de la
invocación es que se copia el
valor del parámetro real
(numero) a la zona de memoria
donde está declarado el
parámetro de la función: num.
• Aunque la función modifique el
valor recibido, lo hace sobre
otra zona de memoria, por lo
tanto no se modifica el valor de
la variable escalar
perteneciente al programa que
invovó a la función.
Interface Software-Hardware: La Pila
• Las variables locales a la función se implementan
en una zona de memoria llamada pila.
• La pila de memoria funciona como una pila de
platos: solo vemos el que está arriba, y
empezamos a lavar desde el último que apilamos
hasta el primero. Puede ser que mientras estés
lavando los platos en la cocina llegue tu mamá
del comedor con MUCHOS mas platos para lavar
que apilará sobre el último apilado.
Gestión de Memoria : la Pila (1)
• Cada función activada tiene en la pila una
zona que le es propia: bloque de activación.
• Por ejemplo: este es el aspecto de la pila con
la zona reservada a la función main() cuando
ésta es activada, que contiene dos variables
locales: bitsnumero y numero. (ver
transparencia 10)
Bloques de Activación (2)
• Despues que el usuario introdujo el número 128
• Cuando se produce la llamada a la función bits
Bloques de Activación (3)
• El parámetro num recibe una copia del contenido
de numero y la variable b se inicializa en 0
• Después de ejecutar el bucle de bits
Bloque de activación (4)
• Inmediatamente ANTES de ejecutar la sentencia
return, se eliminan las variables locales de la
función y queda solamente el valor de retorno
• La sentencia return vuelve a la siguiente
sentencia despues de la invocación. EL valor de
retorno se copia en la variable bitsnumero
Interface Software-Hardware
• Veamos, para entender el tema de variables
locales, parámetros y valores de retorno,
como se implementa el código de una función
y cómo se activa.
• Es decir, veamos el código ensamblador de
una función y su llamada, puesto que es el
compilador el que genera el código que
reserva memoria en la pila.
gcc –S bits.c
.file
.text
"bits.c"
.def
_bits;
pushl
movl
subl
movl
%ebp
%esp, %ebp
$16, %esp
$0, -4(%ebp)
incl
movl
shrl
movl
cmpl
jne
movl
leave
ret
-4(%ebp)
8(%ebp), %eax
%eax
%eax, 8(%ebp)
$0, 8(%ebp)
L2
-4(%ebp), %eax
.globl _bits
.scl
2;
.type
32;
.endef
_bits:
ESP
L2:
BA de bits
-4
b
EBP
EBP
+4
@ret a main
+8
Copia de numero
BA de main
(parte)
Interface Hardware-Software
• Toda función debe construir y destruir su BA:
– Salvar registros que utilize (push)
– Reservar espacio en la pila (restar a ESP, de 4 en 4)
– Obtener los parámetros
– Operar, ejecutar…
– Copiar a la pila o a registro (aquí es a registro) el
valor de devolución de la función
– Liberar memoria (leave)
– Retornar (return)
Variables Globales
• Las variables globales residen en una zona
especial de memoria, no en la pila. Viven
durante toda la ejecución del programa. Es
decir, son permanentes.
Parámetros vectoriales:paso por
referencia
• Un parámetro de tipo
vector se pasa
copiando la dirección
del vector.
• A esta manera de
pasar parámetros se le
llama por referencia.
• Cuando se pasa la
dirección de la
estructura, los cambios
producidos por la
función ocurren sobre
la estructura, y por lo
tanto, a la vuelta de la
función, el vector
queda modificado
Parámetros Vectoriales
• El lenguaje C define que un vector NO se copia
elemento a elemento, sino que se copia su
dirección.
• De esta manera se ven los BA de main y la
función.
Paso por referencia utilizando
punteros
• Un puntero es un tipo de dato. Su valor es una
referencia o dirección de memoria.
• Al declarar una variable de tipo
puntero, se debe especificar el tipo
del valor apuntado (int, char, long,
float, etc). Esto se hace de la
siguiente manera:
– int * a; // a es un puntero a entero
– char* c; // c es un puntero a
carácter
•
Si una función espera un puntero
como parámetro, la función que la
invoca debe pasarle la dirección de
la variable, utilizando para ello el
operador &
C solo usa paso de parámetros por
valor
• Asi es. Por eso es que nos complica la
existencia teniendo que usar el operador *
cada vez que pasamos una variable por
referencia.
• Paso por referencia en C significa paso por
valor de su dirección.
Paso de matrices o vectores
multidimensionales
• Este código no funciona….
• Porque para calcular a[i][j] el compilador debe saber
cuantas columnas hay en cada fila…. Y no hay manera
de saberlo en la función maximo
Matrices o vectores
multidimensionales
• En general, si el vector tiene N dimensiones,
necesitamos pasar como parámetro las N-1
dimensiones. (la primera dimensión no es
necesario).
• El tipo de retorno de una función NO puede
ser un vector (recuerden que no hay
asignación para vectores)
Sobre archivos, funciones y variables
• Todos los objetos en C deberán declararse
antes de usarse.
• Las variables y funciones no declaradas en el
archivo donde son referenciadas o invocadas,
deben declararse como externas:
– extern int a;
– extern int potencia(float x, int y);
• Las variables locales no tienen visibilidad fuera
de la función que las contiene.
Euler 12: ¡Hacerlo con Funciones!
The sequence of triangle numbers is generated by adding the natural numbers.
So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.
The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred
divisors? (500 divisores).
Aclaración: se refiere a los divisores, ¡no a los factores primos!
Descargar