Funciones
Funciones
Funciones
Profesor:
Lenguajes Electrnicos
Apunte N3
1. FUNCIONES
Una funcin es una parte de cdigo independiente del programa principal y de otras funciones, que
puede ser llamada envindole unos datos (o sin enviarle nada), para que realice una determinada tarea y/o
proporcione unos resultados. Las funciones son una parte muy importante del lenguaje C. En los apartados
siguientes se describen los aspectos ms importantes de las funciones.
2. Utilidad de las funciones
Parte esencial del correcto diseo de un programa es su modularidad, esto es su divisin en
partes ms pequeas de finalidad muy concreta. En C estas partes de cdigo reciben el nombre de
funciones. Las funciones facilitan el desarrollo y mantenimiento de los programas, evitan errores, y ahorran
memoria y trabajo innecesario. Una misma funcin puede ser utilizada por diferentes programas, y por tanto
no es necesario reescribirla. Adems, una funcin es una parte de cdigo independiente del programa
principal y de otras funciones, manteniendo una gran independencia entre las variables respectivas, y
evitando errores y otros efectos colaterales de las modificaciones que se introduzcan.
Mediante el uso de funciones se consigue un cdigo limpio, claro y elegante. La adecuada
divisin de un programa en funciones constituye un aspecto fundamental en el desarrollo de programas de
cualquier tipo. Las funciones, ya compiladas, pueden guardarse en libreras. Las libreras son conjuntos
de funciones compiladas, normalmente con una finalidad anloga o relacionada, que se guardan bajo un
determinado nombre listas para ser utilizadas por cualquier usuario.
3. Definicin de una funcin
La definicin de una funcin consiste en la definicin del cdigo necesario para que sta realice
las tareas para las que ha sido prevista. La definicin de una funcin se debe realizar en alguno de los
ficheros que forman parte del programa. La forma general de la definicin de una funcin es la siguiente:
tipo_valor_de_retorno
nombre_funcion(lista de argumentos con tipos)
{
declaracin de variables y/o de otras funciones
codigo
return (expresin);
// optativo
}
La primera lnea recibe el nombre de encabezamiento (header) y el resto de la definicin encerrado
entre llaves es el cuerpo (body) de la funcin. Cada funcin puede disponer de sus propias variables,
declaradas al comienzo de su cdigo. Estas variables, por defecto, son de tipo auto, es decir, slo son
visibles dentro del bloque en el que han sido definidas, se crean cada vez que se ejecuta la funcin y
permanecen ocultas para el resto del programa. Si estas variables de definen como static, conservan su valor
entre distintas llamadas a la funcin. Tambin pueden hacerse visibles a la funcin variables globales
definidas en otro fichero (o en el mismo fichero, si la definicin est por debajo de donde se utilizan),
declarndolas con la palabra clave extern.
El cdigo ejecutable es el conjunto de instrucciones que deben ejecutarse cada vez que la funcin
es llamada. La lista de argumentos con tipos, tambin llamados argumentos formales, es una lista de
declaraciones de variables, precedidas por su tipo correspondiente y separadas por comas (,). Los
argumentos formales son la forma ms natural y directa para que la funcin reciba valores desde el
programa que la llama, correspondindose en nmero y tipo con otra lista de argumentos -los argumentos
Lenguajes Electrnicos
Apunte N3
actuales- en el programa que realiza la llamada a la funcin. Los argumentos formales son declarados en
el encabezamiento de la funcin, pero no pueden ser inicializados en l.
Cuando una funcin es ejecutada, puede devolver al programa que la ha llamado un valor (el valor de
retorno), cuyo tipo debe ser especificado en el encabezamiento de la funcin (si no se especifica, se supone
por defecto el tipo int). Si no se desea que la funcin devuelva ningn valor, el tipo del valor de retorno
deber ser void.
La sentencia return permite devolver el control al programa que llama. Puede haber varias sentencias
return en una misma funcin. Si no hay ningn return, el control se devuelve cuando se llega al final del
cuerpo de la funcin. Le palabra clave return puede ir seguida de una expresin, en cuyo caso sta es
evaluada y el valor resultante devuelto al programa que llama como valor de retorno (si hace falta, con
una conversin previa al tipo declarado en el encabezamiento). Los parntesis que engloban a la expresin
que sigue a return son optativos.
El valor de retorno es un valor nico: no puede ser un vector o una matriz, aunque s un puntero
a un vector o a una matriz. Sin embargo, el valor de retorno s puede ser una estructura, que a su vez
puede contener vectores y matrices como elementos miembros.
Como ejemplo supngase que se va a calcular a menudo el valor absoluto de variables de tipo
double. Una solucin es definir una funcin que reciba como argumento el valor de la variable y devuelva
ese valor absoluto como valor de retorno. La definicin de esta funcin podra ser como sigue:
double valor_abs(double x)
{
if (x < 0.0)
return -x;
else
return x;
}
Mediante una llamada a la funcin. En efecto, cuando una funcin es llamada sin que previamente haya
sido declarada o definida, esa llamada sirve como declaracin suponiendo int como tipo del valor de
retorno, y el tipo de los argumentos actuales como tipo de los argumentos formales. Esta prctica es muy
peligrosa (es fuente de numerosos errores) y debe ser evitada.
b)
Mediante una definicin previa de la funcin. Esta prctica es segura si la definicin precede a la llamada,
pero tiene el inconveniente de que si la definicin se cambia de lugar, la propia llamada pasa a ser
declaracin como en el caso a).
c)
Mediante una declaracin explcita, previa a la llamada. Esta es la prctica ms segura y la que hay que
Lenguajes Electrnicos
Apunte N3
tratar de seguir siempre. La declaracin de la funcin se hace mediante el prototipo de la funcin, bien
fuera de cualquier bloque, bien en la parte de declaraciones de un bloque.
C++ es un poco ms restrictivo que C, y obliga a declarar explcitamente una funcin antes de llamarla.
La forma general del prototipo de una funcin es la siguiente:
tipo_valor_de_retorno
Esta forma general coincide sustancialmente con la primera lnea de la definicin -el encabezamiento-,
con dos pequeas diferencias: en vez de la lista de argumentos formales o parmetros, en el prototipo
basta incluir los tipos de dichos argumentos. Se pueden incluir tambin identificadores a continuacin
de los tipos, pero son ignorados por el compilador. Adems, una segunda diferencia es que el prototipo
termina con un carcter (;). Cuando no hay argumentos formales, se pone entre los parntesis la palabra void,
y se pone tambin void precediendo al nombre de la funcin cuando no hay valor de retorno.
Los prototipos permiten que el compilador realice correctamente la conversin del tipo del valor de
retorno, y de los argumentos actuales a los tipos de los argumentos formales. La declaracin de las
funciones mediante los prototipos suele hacerse al comienzo del fichero, despus de los #define e
#include . En muchos casos particularmente en programas grandes, con muchos ficheros y muchas
funciones, se puede crear un fichero (con la extensin .h) con todos los prototipos de las funciones
utilizadas en un programa, e incluirlo con un #include en todos los ficheros en que se utilicen dichas
funciones.
La llamada a una funcin se hace incluyendo su nombre en una expresin o sentencia del programa
principal o de otra funcin. Este nombre debe ir seguido de una lista de argumentos separados por comas y
encerrados entre parntesis. A los argumentos incluidos en la llamada se les llama argumentos actuales, y
pueden ser no slo variables y/o constantes, sino tambin expresiones. Cuando el programa que llama
encuentra el nombre de la funcin, evala los argumentos actuales contenidos en la llamada, los convierte si
es necesario al tipo de los argumentos formales, y pasa copias de dichos valores a la funcin junto
con el control de la ejecucin.
El nmero de argumentos actuales en la llamada a una funcin debe coincidir con el nmero de
argumentos formales en la definicin y en la declaracin. Existe la posibilidad de definir funciones con un
nmero variable o indeterminado de argumentos. Este nmero se concreta luego en el momento de
llamarlas. Las funciones printf() y scanf(), son ejemplos de funciones con nmero variable de argumentos.
Cuando se llama a una funcin, despus de realizar la conversin de los argumentos actuales, se ejecuta
el cdigo correspondiente a la funcin hasta que se llega a una sentencia return o al final del cuerpo de la
funcin, y entonces se devuelve el control al programa que realiz la llamada, junto con el valor de retorno
si es que existe (convertido previamente al tipo especificado en el prototipo, si es necesario). Recurdese
que el valor de retorno puede ser un valor numrico, una direccin (un puntero), o una estructura, pero no
una matriz o un vector.
La llamada a una funcin puede hacerse de muchas formas, dependiendo de qu clase de tarea
realice la funcin. Si su papel fundamental es calcular un valor de retorno a partir de uno o ms
argumentos, lo ms normal es que sea llamada incluyendo su nombre seguido de los argumentos
actuales
en una expresin aritmtica o de otro tipo. En este caso, la llamada a la funcin hace el papel de un
operando ms de la expresin. Obsrvese cmo se llama a la funcin seno en el ejemplo siguiente:
a = d * sin(alpha) / 2.0;
En otros casos, no existir valor de retorno y la llamada a la funcin se har incluyendo en el
programa una sentencia que contenga solamente el nombre de la funcin, siempre seguido por los argumentos
Lenguajes Electrnicos
Apunte N3
actuales entre parntesis y terminando con un carcter (;). Por ejemplo, la siguiente sentencia llama a
una funcin que multiplica dos matrices (nxn) A y B, y almacena el resultado en otra matriz C. Obsrvese
que en este caso no hay valor de retorno (un poco ms adelante se trata con detalle la forma de pasar
vectores y matrices como argumentos de una funcin):
prod_mat(A, B, C);
Hay tambin casos intermedios entre los dos anteriores, como sucede por ejemplo con las funciones
de entrada/salida .Dichas funciones tienen valor de retorno, relacionado de ordinario con el nmero de
datos ledos o escritos sin errores, pero es muy frecuente que no se haga uso de dicho valor y que se
llamen al modo de las funciones que no lo tienen.
Ejemplo: la declaracin y la llamada de la funcin valor_abs(), se podra realizar de la forma
siguiente. Supngase que se crea un fichero prueba.c con el siguiente contenido:
// fichero prueba.c
#include <stdio.h>
double valor_abs(double);
// declaracin
}
La funcin valor_abs() recibe un valor de tipo double. El valor de retorno de dicha funcin (el valor
absoluto de y), es introducido en la expresin aritmtica que calcula z.
5. Paso de argumentos por valor y por referencia
En la seccin anterior se ha comentado que en la llamada a una funcin los argumentos actuales
son evaluados y se pasan copias de estos valores a las variables que constituyen los argumentos formales
de la funcin. Aunque los argumentos actuales sean variables y no expresiones, y haya una correspondencia
biunvoca entre ambos tipos de argumentos, los cambios que la funcin realiza en los argumentos formales no
se trasmiten a las variables del programa que la ha llamado, precisamente porque lo que la funcin ha recibido
son copias. El modificar una copia no repercute en el original. A este mecanismo de paso de argumentos a una
funcin se le llama paso por valor. Considrese la siguiente funcin para permutar el valor de sus dos
argumentos x e y:
void permutar(double x, double y)
{
double temp;
temp = x;
x = y;
y = temp;
}
La funcin anterior podra ser llamada y comprobada de la siguiente forma:
Lenguajes Electrnicos
Apunte N3
#include <stdio.h>
void main(void)
{
double a=1.0, b=2.0;
void permutar(double, double);
printf("a = %lf, b = %lf\n", a, b);
permutar(a, b);
printf("a = %lf, b = %lf\n", a, b);
}
Compilando y ejecutando este programa se ve que a y b siguen teniendo los mismos valores antes y
despus de la llamada a permutar(), a pesar de que en el interior de la funcin los valores s se han
permutado (es fcil de comprobar introduciendo en el cdigo de la funcin los printf() correspondientes). La
razn est en que se han permutado los valores de las copias de a y b, pero no los valores de las
propias variables. Las variables podran ser permutadas si se recibieran sus direcciones (en realidad,
copias de dichas direcciones). Las direcciones deben recibirse en variables puntero (variables que
guardan direcciones de memoria), por lo que los argumentos formales de la funcin debern ser punteros.
Una versin correcta de la funcin permutar() que pasa direcciones en vez de valores sera como sigue:
void permutar(double *x, double *y)
{
double temp;
temp = *x;
*x = *y;
*y = temp;
}
que puede ser llamada y comprobada de la siguiente forma:
#include <stdio.h>
void main(void)
{
double a=1.0, b=2.0;
void permutar(double *, double *);
printf("a = %lf, b = %lf\n", a, b);
permutar(&a, &b); /*Observar el operador & que se
utiliza para pasar por referencia las variables */
Lenguajes Electrnicos
Apunte N3
punteros y dichos datos se pasan por referencia, lo cual tiene la ventaja adicional de que no se gasta
memoria y tiempo para pasar a las funciones copias de cantidades grandes de informacin.
Un caso distinto es el de las estructuras de datos, y conviene tener cuidado. Por defecto las estructuras
de datos se pasan por valor, y pueden representar tambin grandes cantidades de datos (pueden contener
arrays como miembros) de los que se realizan y transmiten copias, con la consiguiente prdida de eficiencia.
Por esta razn, las estructuras se suelen pasar de modo explcito por referencia, por medio de punteros
a las mismas.