Amoor

Amoor gy lindajen no•R6pR ‘E, 2011 12 pagos 1. FUNCIONES 1. 1 CONCEP OS Y FUNDAMENTOS DE LAS FUNCIONES La definición de una función puede ubicarse en cualquier lugar del programa, con sólo dos restricciones: debe hallarse luego de dar su prototipo, y no puede estar dentro de la definición de otra función ( Incluida maln() Es decir que a diferencia de pascal, en C las definiciones no pueden anidarse. NOTA: no confundir definición con llamada; una función puede llamar a tantas otras como desee .

La definición debe comenzar con un encabezamiento, que debe oincidir totalmente con el prototipo declarado para la misma, y a continuacion del mismo, encerradas por llaves se escribirán las sentencias que la componen; por ejemplo: #include float mi_funcion(int termina en main() floatk; int p; double z; k mi_funcion( p, z PACE 1 or12 Sv. ipe to View ION observe que l* LLAMADA a la función *l Estas informaciones están contenidas en la DECLARACION del PROTOTIPO DE LA FUNCION.

Formalmente dicha declaración queda dada por : tipo del valor de retorno de tipos de parámetros) Pongamos algunos ejemplos float mi_funcion(int i, double j ) ; double otra_funcion(void) ; tra_mas(long p) ; void la_ultima(long double z, char y, intx, unsigned long w) ; El primer término del prototipo da, como hemos visto el tipo del dato retornado por la función; en caso de obviarse el mismo se toma, por omisión, el tipo int.

Sin embargo, aunque la función devuelva este tipo de dato, para evitar malas interpretaciones es conveniente explicitarlo Ya que el «default» del tipo de retorno es el int, debemos indicar cuando la función NO retorna nada, esto se realiza por medio de la palabra VOID (sin valor). De la misma manera se actúa, cuando no se le enviarán argumentos. Más adelante se profundizará sobre el tema de los argumentos y sus características. La declaración debe anteceder en el programa a la definición de la función.

Es normal, por razones de legibil dad de la documentación, encontrar todas las declaraciones de las funciones usadas en el programa, en el HEADER del mismo, Junto con los include de los archivos *. h que tienen los prototipos de las funciones de Librería. Si una ó más de nuestras funciones es usada habitualmente, podemos disponer su pro rchivo de texto, e incluirlo las veces que necesitemos, en capítulos previos. AMBITO DE LAS VARIAB ES (SCOPE)

VARIABLES GLOBALES Hasta ahora hemos diferenciado a las variable segun su «tipo’ (int, char double, etc), el cual se refería, en última instancia, a la cantidad de bytes que la conformaban. Veremos ahora que hay otra diferenciación de las mismas, de acuerdo a la clase de memoria en la que residen Si definimos una variable AFUERA de cualquier función (incluyendo esto a main() ), estaremos frente a lo denominado VARIABLE GLOBAL Este tipo de variable será ubicada en el segmento de datos de la memoria utilizada por el programa, y existirá todo el tiempo que esté ejecutandose este

Este tipo de variables son automaticamente inicializadas a CERO cuando el programa comienza a ejecutarse Son accesibles a todas las funciones que esten declaradas en el mismo, por lo que cualquiera de ellas podrá actuar sobre el valor de las mismas. Por ejemplo : double double variable_global , variable_global ); i = una_funcion() ; se imprimirá 0 V printf() del programa principal se la imprime, demostrandose que está automaticamente inicializada a cero .

Luego es incrementada por una_funcion() que devuelve ademas una copia de su valor, el cual es asignado a i que, si es impresa ostrará un valor de uno, pero tambien la variable_global ha quedado modificada, como lo demuestra la ejecución de la sentencia siguiente. Luego main() tambien modifica su valor , lo cual es demostrado por el printf() siguiente. Esto nos permite deducir que dicha variable es de uso público, sin que haga falta que ninguna función la declare, para actuar sobre ella. Las globales son a los demás tipos de variables, lo que el GOTO es a los otros tipos de sentencias .

Puede resultar muy difícil evaluar su estado en programas algo complejos, con múltiples llamados condicionales a funciones que as afectan, dando comunmente orígen a errores muy engorrosos de corregir VARIABLES LOCALES A diferencia de las anteriores, las variables definidas DENTRO de una función, son denominadas VARIABLES LOCALES a la misma, a veces se las denomina también como AUTOMATICAS, ya que son creadas y destruidas automaticamente por la llamada y el retorno de una función, respectivamente Estas variables se ubican en la pila dinámica (stack) de memoria destinandosele un espacio en la misma cuando se las define dentro de una función, y borrándose cuando la misma devuelve el control del programa, a quien la haya invocado.

Este método permite que, aunque se haya definido un gran número de variables en un programa, estas no ocupen memoria simultaneamente en el tiempo, y solo vayan incrementando el stack 40F programa, estas no ocupen memoria simultaneamente en el tiempo, y solo vayan incrementando el stack cuando se las necesita, para luego, una vez usadas desaparecer, dejando al stack en su estado original . El identificador ó nombre que se la haya dado a una variable es sólo relevante entonces, para la función que la haya definido, pudiendo existir entonces variables que tengan el mismo ombre, pero definidas en funciones distintas, sin que haya peligro alguno de confusión La ubicación de estas variables locales, se crea en el momento de correr el programa, por lo que no poseen una dirección prefijada, esto impide que el compilador las pueda inicializar previamente. Recuerdese entonces que, si no se las inicializa expresamente en el momento de su definición, su valor será indeterminado (basura) .

VARIABLES LOCALES ESTATICAS Las variables locales vistas hasta ahora, nacen y mueren con cada llamada y finalización de una función, sin embargo muchas veces eria util que mantuvieran su valor, entre una y otra llamada a la funcion sin por ello perder su ámbito de existencia, es decir seguir siendo locales sólo a la función que las defina. En el siguiente ejemplo veremos que esto se consigue definiendo a la variable con el prefacio static. VARIABLES DE REGISTRO Otra posibilidad de almacenamiento de las variables locales es, que en vez de ser mantenidas en posiciones de la memoria de la computadora, se las guarde en registros internos del Microprocesador que conforma la CPU de la misma .

De esta manera el acceso a ellas es mucho más directo y rápido, umentando la velocidad de ejecución del programa. Se suel s OF V más directo y rápido, aumentando la velocidad de ejecución del programa. Se suelen usar registros para almacenar a los contadores de los POR, WHILE, etc. Lamentablemente, en este caso no se puede imponer al compilador, este tipo de variable, ya que no tenemos control sobre los registros libres en un momento dado del programa, por lo tanto se SUGIERE, que de ser posible, ubique la variable del modo descripto. El prefacio en éste caso será : register int var_reg ; Hay que recalcar que esto es sólo válido para variables LOCALES, iendo imposible definir en un registro a una global.

Por otra parte las variables de registro no son accesibles por dirección, como se verá más adelante VARIABLES EXTERNAS Al DEFINIR una variable, como lo hemos estado haciendo hasta ahora, indicamos al compilador que reserve para la misma una determinada cantidad de memoria, (sea en el segmento de memoria de datos, si es global ó en el stack, si es local), pero debido a que en C es normal la compilación por separado de pequeños módulos, que componen el programa completo, puede darse el caso que una función escrita en un archivo dado, deba sar una variable global definida en otro archivo. Bastará para poder hacerlo, que se la DECLARE especificando que es EXTERNA a dicho módulo, lo que implica que está definida en otro lado . Supongamos que nuestro programa está compuesto por sólo dos módulos: mod_prin. c y mod_sec. c los cuales se compilarán y enlazarán juntos, por medio del compilador y el linker, por ejemplo corriendo: bcc mod_prin. c mod_sec. c si usaramos el compilador de Borland . Si en el primer módulo (mod_prin. c) aparece una varia 6 OF V mod_sec. c si usaramos el compilador de Borland Si en el primer módulo (mod_prin. aparece una variable global, definida como double varl = 5 El segundo módulo, ubicado en un archivo distinto de aquel, podrá referenciarla mediante la declaración de la misma extern double varl • Notesé que la inialización de la variable sólo puede realizarse en su DEFINICION y no en la declaración. Esta última, no reserva memoria para la variable sino que sólo hace mención que la misma ha sido definida en otro lado . Será finalmente el Linker el que resuelva los problemas de direccionamiento de la variable al encadenar los dos módulos compilados . 1. 4 ARGUMENTOS Y TIPOS DE PARAMETROS DE LAS FUNCIONES Supongamos que en un determinado programa debemos calcular repetidamente el valor medio de dos variables, una solución razonable sería crear una función que realice dicho cálculo, y llamarla cada vez que se necesite. Para ello será necesario, en cada llamada, pasarle los valores de las variables para que calcule su valor medio.

Esto se define en la declaración de la funcion especificando, no solo su valor de retorno sino también el tipo de argumentos que recibe : double valor_medio(double x, double y) ; de esta declaración vemos que la función valor_medio recibe dos rgumentos ( x ey ) del tipo double y devuelve un resultado de ese mismo tipo . Cuando definamos a la función en sí, deberemos incluir parámetros para que alberguen los valores recibidos, así escribiremos: double x, double y ) ((x+Y)/2. O) NOTA: No es necesario que los NOMBRES de los párametros coincidan con los declarados previamente, es decir que hubiera sido equivalente escribir: double a, double b) etc, sin embargo es una buena costumbre mantenerlos igual.

En realidad en la declaración de la función, no es necesario incluir el nombre de los parámetros, bastaría con poner solo el tipo, sin mbargo es práctica generalizada, explicitarlos a fin de hacer más legible al programa Aquí estamos utilizando la sintaxis moderna del lenguaje C, pudiendose encontrar en versiones arcaicas, definiciones equivalentes como : double ó double double) double x; double y; Sin embargo es preferible utilizar la nomenclatura moderna, ya que esta facilita la rápida comprensión del programa . Veamos un ejemplo, para determinar el comportamiento de los parámetros, Supongamos desear un programa que calcule el valor medio de dos variables incrementadas en un valor fijo, es decir: (x + incremento ) + (y + incremento ) ) / 2. Lo podríamos resolver de la siguiente forma : Declaración de la funció sus parámetros *l 8 OF V el segundo valor: I’); el incremento resultado = valor_medio( x, y, z); l* llamada a la función y pasaje de argumentos de la operación: %lf», resultado) ; printf(»

VaIor con que quedaron las variables: ; primer valor : x); Segundo valor: ‘i, y) ; Incremento : I’, z); l* Definición de la función y sus parámetros double valor_medio( double p_valor, double s_valor, double inc ) p_valor inc ; s valor +7 In return ( (p_valor + s_valor ) / 2. 0 ) ; Veamos primero cual seria la salida de pantalla de este programa • SALIDA DEL EJEMPLO Ingrese el primer valor: Ingrese el segundo valor: [SUPONGAMOS ESCRIBIR: 10. 0] : 8. 0] argumento y una variable local, es que ésta no es inicializada automaticamente, mientras que aquellos lo són, a los valores de los argumentos colocados en la expresión de llamada.

Acá debemos remarcar un importante concepto: éste pasaje de datos a las funciones, se realiza COPIANDO el valor de las variables en el stacky No pasandoles las variables en sí. Esto se denomina: PASAJE POR VALOR y garantiza que dichas variables o sean afectadas de ninguna manera por la función invocada. Una clara prueba de ello es que, en la función valor_medio() se incrementa p_valor y s_valor, sumandoseles el contenido del parámetro inc. Sin embargo cuando, luego de retornar al programa principal, imprimimos las variables cuyos valores fueron enviados como parametros, vemos que conservan sus valores iniciales. Veremos más adelante que otras estructuras de datos pueden ser pasadas a las funciones por direcciones en vez de por valor, pudiendo aquellas modificarlas a gusto .

Debe aclararse que, el pasaje de argumentos, es también una OPERACION, por lo que las variables pasadas quedan afectadas por las reglas de Conversión Automática de Tipo, vistas en el Capítulo 2. Como ejemplo, si x hubiera sido definida en la función main() como int, al ser pasada como argumento a valor_medio() seria promovida a double. Especlal cuidado debe tenerse entonces con los errores que pueden producirse por redondeo ó truncamiento, siendo una buena técnica de programación hacer coincidir los tipos de los argumentos con los de los parámetros. 2 ARREGLOS Enclase ya conocimos algunos tipos básicos como por ejemplo los tipos char, inty float. El le 2