La función es un módulo o parte de una aplicación informática que forma, un bloque, una unidad de código. El uso de funciones es una característica peculiar y muy importante en el lenguaje C, pues permite un desarrollo modular dando sencillez a éste y precisión a la depuración de programas.
Vamos a diferenciar en el empleo de las funciones tres conceptos importantes:
Definición de la función
Declaración de la función
Llamada a la función
a)
Definición
de la función
Una función se define de forma similar a la función main(), haciéndose una sola vez en el programa. Su formato genérico es el mostrado a continuación.
{
<cuerpo de la función>
}
Tipo: es el tipo de dato que puede retornar la función (por defecto, se considera int).
Nombre_función: El nombre de la función debe cumplir las normas establecidas para los identificadores.
Tipo Param_n: Es el tipo y nombre de cada parámetro formal de la función, formando una lista separada por comas. Es posible que la función no lleve parámetros pero siempre deberá tener los paréntesis.
Cuerpo de la función:Es el conjunto de sentencias de definición de datos, de declaraciones y de sentencias de ejecución necesarias para la realización de una determinada tarea.
float Calc_Media ( float suma, int num)
{
float med;
med = suma /
num;
return med;
}
b) Declaración de la función
En el caso de que la función que se va a llamar esté definida en el
programa antes de la función que la llama no existe ningún problema, pues la
definición de la función sirve como declaración (la función que llama ya conoce
las características de la función a llamar. Sin embargo, si la función que se
va a llamar está definida en el programa después de tener definida la función
que llama, hay que realizar una declaración o prototipo de la función por medio
de una sentencia que en realidad es igual al encabezamiento de la definición de
la función.
La sentencia de
declaración debe preceder a las llamadas de la función dentro del programa,
pudiendo estar situada dentro de la función que hace la llamada o a nivel
global para todas las funciones.
Formato de la declaración:
Declaración de la función:
Float calc_valor(int x, flota y);
Otras posibles declaraciones
Float calc_valor (int, float);
Float calc_valor(int a, float b);
Definición de la función:
Float calc_valor(int x , float y)
{
}
La clase de almacenamiento de una variable viene determinada por dos características que son, su ámbito o alcance y su tiempo de almacenamiento. El alcance es la parte de código del programa donde la variable es conocida y por tanto es accesible. El tiempo de almacenamiento es el tiempo de vida o duración en memoria de la variable durante la ejecución del programa.
La clase de almacenamiento de una variable depende del lugar donde está definida dentro del programa y del especificador correspondiente a la clase de almacenamiento que la puede preceder en su definición.
Teniendo en cuenta el lugar donde están definidas las variables, éstas se pueden clasificar en los siguientes tipos:
Variables locales
Está definida al comienzo
del bloque de sentencias (cuerpo) de una función
Su alcance es el bloque de
sentencias de la función.
Variables globales
Está definida fuera de las
funciones del programa y normalmente al comienzo del mismo.
Su alcance es todas las
funciones definidas en ese módulo.
Variables formales
Son variables que se
definen como parámetros de una función.
<Especificador_clase_almacenamiento> Tipo_basico_dato
Nombre_variable;
Los especificadores básicos son:
auto (automática):Se considera a las variables locales, por defecto ya tienen este especificador
extern (Externa): Son variables que aun definiéndose dentro de una función puedan ser accesibles des de fuera de la función.
Static (Estática): Utilizan el especificador de clase de almacenamiento static y su funcionamiento depende de que las variables sean locales o globales.
Statica local: Es una variable local, aunque su valor permanece almacenado después de varias llamadas a la función, aunque no se puede variar desde fuera de la función.
Statica global: Es una variable que está al alcance de cualquier funcion del fichero.
Variables Registro: Se aplica a variables o a parámetros formales mediante el especificador de clase de almacenamiento register, este valor de la variable quedará almacenado en uno de los registros de la CPU en lugar de la memoria, permitiendo al compilador acceder a ella mucho más rápido. Debe ser un tipo de variable a la que se deba acceder repetidas veces.
RETORNO DE UNA FUNCIÓN
Es el valor que retorna la función. También si se quiere salir de la función se utiliza la sentencia return.
Función que indica el valor menor de dos valores:
Float menor_num( float x, float y)
{
if (x < y) return x;
else
return y;
}
printf(“ El menor es %f ”, menor_num(a,b);
CLASES DE FUNCIONES
Las funciones se pueden clasificar teniendo en cuenta si retornan o no un valor, y si el valor retornado es necesario que sea recogido por la función que llama.
Funciones que no retornan un valor (Procedimientos)
Void Escribe_puntos(int x)
{
int n;
for (n=0; n< x; n++)
printf(“.”);
}
Funciones que retornan un valor
Float Raiz_cuadrada(int x)
{
if(x >= 0
return sqrt(x);
else
return –1;
}
PARÁMETROS DE FUNCIONES
La interconexión o acoplamiento de funciones se efectúa por la compartición de variables. Se puede realizar utilizando variables globales o utilizando parámetros.
Interconexión con variables globales
Es la forma más sencilla, sobre todo, cuando el programa es controlado por un solo programador, pero tiene el gran inconveniente de que se pueden producir efectos laterales pues las variables pueden ser accedidas y modificadas por cualquier función del programa.
Interconexión con parámetros
Los parámetros son variables de enlace entre funciones de tal forma que los parámetros formales de una función son variables locales que se crean y reciben sus valores al entrar en la función (procedentes de los valores o direcciones de los parámetros locales de la función que llama) y se destruyen al salir de la misma. Los parámetros formales se emplean dentro de la función como el resto de las variables locales.
Paso por valor
#include <stdio.h>
float sum¡_num(float x, float y);
void main(void)
{
float a, b;
printf(“\n Introduccir dos números: “);
scanf(“%f%f”, &a, b&);
printf(“\n La suma vale: %f, sum_num(a,b));
}
float sum_num(float x, float y)
{
return(x + y);
}
Paso por dirección o referencia
Los parámetros formales deberán de ser tipo puntero, la dirección de los parámetros actuales, y por tanto, las modificaciones que se realicen en el valor de las variables apuntadas por los parámetros formales afectarán al valor de los parámetros actuales. Con este paso de parámetros se permite de una forma implícita que una función retorne más de un valor a la función que llama.
Poner en memoria la mitad de valor de dos variables numéricas:
#include <stdio.h>
void pone_mitad( float *x, float *y);
void main(void)
{
float a, b;
printf(“Introducir dos números”);
scanf(“%f%f”,&a,&b);
printf(“Los valores de a y b son: %f %f”,a ,b);
}
void pone_mitad(*float *x, float *y)
{
x = (*x)/2;
y = (*y)/2;
}
FUNCIONES Y ARRAYS
El paso de arrays a una función lo contemplaremos en este texto para el caso de arrays unidimensionales o vectores, considerando que para arrays multidimensionales se hará de forma similar a los vectores.
Paso de parámetros de forma individual:
#include <stdio.h>
int par_imp(int x);
void main(void)
{
int tab[25], k, p;
printf(“\n Introducir elementos en la tabla”);
for(k=0;k < 25 ; k++) scanf(“%d”, &tab[k]);
p= par_impar(tab[0]);
if (p==1) printf(“El primer elemento es par \n”);
else
printf(“El primer elemento es impar\n”);
}
int par_imp(int x)
{
if (x%2 ==0)
return1;
else
return0;
}
Paso de todo el vector
Cuando se quiere operar en la función con todos los elementos del vector, no se pasan como parámetros todos los elementos, sino que se realiza un paso de un parámetro por dirección, utilizndo el nombre del vector que es una constante puntero que contiene la dirección del primer elemento del vector.
#include <stdio.h>
float media_vector(float *pvec, int n);
void main(void)
{
float vec[45], med;
int j;
printf(“Introducir elementos de la tabla”);
for (j= 0; j<45; j ++)
scanf(“%f”,&vec[j]);
med = media_vector(vec, 45);
printf(“\n La media vale: %0.2f”, med);
}
flota media_vector(flota *pvec, int n)
{
int k;
flota m, sum = 0;
for(k = 0; k < n; k++)
sum = sum + *(pvec + k);
m = sum /n;
return m;
}
PARÁMETROS DE MAIN
Hasta ahora hemos empleado la función main() sin parámetros, indicándolo de forma explícita con void entre paréntesis. Sin embargo se pueden pasar parámetros desde la línea de órdenes del sistema operativo, a la función principal del programa. Los parámetros que deben utilizar son argc y argv, nombres que son tradicionales pero pueden tener cualquier denominación.
El parámetro argc (Argument count) es un número entero que maneja el sistema y que contiene el número de parámetros en la línea de órdenes, considerando el nombre del programa como el primer parámetros. Por tanto, el valor mínimo de argc es 1.
El parámetros argv(argument value) es una tabla de punteros a cadena de caracteres. Estas cadenas siguen al nombre del programa cuando se utiliza para su ejecución. Cada parámetro de la línea de órdenes debe estar separado por un espacio o una tabulación de tal forma que si se quiere tener como parámetro una cadena que contenga espacios o tabulaciones hay que cerrarla entre dobles comillas.
Formato: void main(int argc, char *argv[]);
Ejemplo:
#include<stdio.h>
void main(int argc, char *argv[])
{
if (argc > 2) {
printf(“Hay demasiados parámetros\n”);
exit(1);
}
else if (argc < 2){
printf(“Falta el nombre del operador \n”);
exit(1);
}
printf(“Hola, como estás %s”, argv[1]);
}
FUNCIONES RECURSIVAS
Una función recursiva es aquella que se llama a sí misma. Se puede utilizar para evitar una estructura iterativa en el programa, pero la versión recursiva tiene una ejecución más lenta debido a las sucesivas llamadas a la función.
La recursividad puede también aplicarse a la función main().
Función que calcula el factorial de un número entero.
Solución con una estructura iterativa |
Solución con una función recursiva. |
Long Fac_Itera(int x) { int k; long fact = 1; for (k = 1 ; k <= x; k ++) Fact = fact * k; Return fact; } |
Long fact_recur(int x) { long fact; if(x==1); return 1; fact = x * fac_recur(x-1); return fact; } |