420 likes | 646 Views
Funciones: conceptos básicos. Un programa “C” está formado por un conjunto de objetos externos que pueden ser variables o funciones. Cualquier programa “C” tiene al menos una función llamada main que es la función principal.
E N D
Funciones: conceptos básicos • Un programa “C” está formado por un conjunto de objetos externos que pueden ser variables o funciones. • Cualquier programa “C” tiene al menos una función llamada main que es la función principal. • Las funciones de “C” son porciones de código ejecutable que devuelven un valor al ser invocadas. Este valor puede depender de los argumentos que se especifiquen en la llamada.
Funciones: conceptos básicos • El intercambio de información entre dos funciones, cuando una llama a la otra, puede realizarse mediante: • el resultado devuelto por la función llamada, • los parámetros de la función llamada, • variables externas accesibles por ambas funciones. • En “C” todas las funciones son externas, ya que no se permite la definición de funciones en el interior de otras funciones.
Definición de funciones • La sintaxis aconsejada (“estilo nuevo”, introducido por el estándar ANSI) para la definición de una función es: [clase][tipo] nombre_función( tipo_1 ident_1 ,... , tipo_n ident_n ); bloque • La sintaxis original (“estilo antiguo”, del “C” de K&R) de la definición de una función es: [clase][tipo] nombre_función( ident1 ,... , ident_n ); tipo_1 ident_1 ,... , tipo_n ident_n; bloque
Definición de funciones • Caso particular de una función sin parámetros: • estilo nuevo (ANSI): [clase][tipo] nombre_función( void ); bloque • estilo antiguo (K&R): [clase][tipo] nombre_función( ); bloque • Si en el estilo antiguo no se proporciona la declaración de uno de los parámetros se considera que es de tipo int
Definición de funciones • tipo indica el tipo del valor devuelto por la función; en caso de no indicarse, se considera que el valor devuelto es de tipo int. • Una función puede devolver un tipo aritmético, un puntero, una estructura, una unión o void (ANSI), pero no puede devolver ni una función ni un array. • nombre_función es el identificador que se utilizará para invocar la función definida.
Definición de funciones • El cuerpo de la función (bloque) especifica el conjunto de sentencias que se ejecutan al invocar a la función, entre ellas, el conjunto de declaraciones y definiciones internas de esa función. • clase especifica la clase de almacenamiento de la función, que puede ser extern o static, siendo extern en el caso de no especificarse nada.
Definición de funciones • Si la función es de clase extern puede utilizarse en todos los ficheros que forman el programa. Debe existir una sola definición de cada función de clase extern entre todos los ficheros que constituyen el programa. • Si la función es de clase static, sólo puede utilizarse en el fichero en que se encuentra su definición; puede existir una definición de una función distinta con el mismo nombre en otro fichero del programa.
Definición de funciones Se utiliza el término: • parámetro formal para referirse a las variables declaradas como argumentos de la función en su definición (las designadas por los identificadores ident_1,... , ident_n). • parámetro actual para referirse a las expresiones proporcionadas como argumentos en una llamada a la función, cuyos valores se asignarán a los correspondientes parámetros formales en el momento de ejecutarse la llamada.
Definición de funciones • Los parámetros formales definen la interfaz de entrada de la función, • se consideran variables automáticas con alcance limitado al cuerpo de la función (bloque) • su nombre puede coincidir con otro identificador externo a la función. • Los parámetros actuales definen la información que se quiere transferir a la función en el momento de invocarla.
Declaración de funciones • La definición de una función sirve como declaración para el resto del fichero en que se encuentra. • Cuando es necesario hacer referencia a una función antes de su definición, o desde otro fichero distinto al de su definición, se debe realizar una declaración anticipada. • La declaración anticipada especifica al compilador al menos el tipo y nombre de la función, para que pueda ser invocada fuera del alcance de su definición.
Declaración de funciones • La sintaxis aconsejada (“estilo nuevo”, introducida por el estándar ANSI) para la declaración de una función es: [clase][tipo] nombre_función( tipo_1 ident_1 ,... , tipo_n ident_n ); • La sintaxis original (“estilo antiguo”, del “C” de K&R) de la declaración de una función es: [clase][tipo] nombre_función( ); • La clase de almacenamiento puede ser extern o static • si se omite el tipo se considera int • si se omite la clase se considera extern
Declaración de funciones:estilo antiguo • Si la llamada de una función ocurre dentro del alcance de una declaración de estilo antiguo el resultado es indefinido: • si el número de parámetros actuales no se corresponde con el número de parámetros formales • si los tipos de los parámetros actuales no concuerdan con los de los correspondientes parámetros formales, después de llevar a cabo las promociones de tipo adecuadas.
Declaración de funciones:declaración implícita • La primera llamada a una función, f, cuando no existe ninguna declaración dentro de cuyo ámbito se encuentre, lleva implícita su declaración como: extern int f( ); en el bloque más interior que contiene la llamada. • Si en el mismo programa se ha definido una función del mismo nombre que devuelve un tipo distinto de int, el resultado es indefinido. • Se considera mala práctica hacer uso de este tipo de declaración implícita.
Prototipos de funciones • El concepto más amplio de declaración de función del estándar ANSI, que incluye la especificación del número y los tipos de los parámetros (el estilo nuevo), se denomina prototipo de función. • Habitualmente, los prototipos de función se sitúan, o bien al principio de cada fichero en que aparece una llamada a la correspondiente función, o bien en un fichero de encabezado que se incluye en cada uno de estos ficheros.
Prototipos de funciones • Los prototipos de función permiten: • la comprobación, en tiempo de compilación, de la correspondencia entre el número de los parámetros actuales y formales (excepción: las funciones variádicas). • la conversión automática, en tiempo de ejecución, de los tipos de los parámetros actuales en los tipos de los parámetros formales (como si se tratara de asignaciones)
Prototipos de funciones • ANSI introdujo un nuevo tipo de datos básico, void, para indicar que una función no devuelve ningún valor, o que la función no tiene parámetros. • Ejemplo: voidhola(void); /* prototipo */ void hola(void) /* definición */ { printf(“Hola\n”); }
Parámetros de una función • Todos los parámetros se pasan por valor, es decir, si se pasa una variable a una función como parámetro actual, se genera una copia de esta variable y la función trabaja sobre esta copia. • La función sólo puede modificar el valor de la copia de la variable que se le pasa como parámetro actual, no puede modificar el valor de la variable en sí.
Parámetros de una función • Una función puede modificar el valor de una variable cuya dirección se le pasa como parámetro actual. • De esta manera, se simula la posibilidad de pasar parámetros por referencia que existe en otros lenguajes (atención al uso del operador unario &).
Reglas de ámbito • Las reglas de ámbito de un lenguaje son aquellas que gobiernan si un segmento de código conoce la existencia de, o tiene acceso a, otro segmento de código. • El ámbito de los identificadores declarados como parámetros formales es la propia función. • El bloque de código más común en cuyo interior se declaran variables es el cuerpo de una función.
Reglas de ámbito • El ámbito de una declaración externa abarca desde el punto en el que se realiza su declaración en un fichero hasta el final de ese fichero. • El ámbito de una declaración interna a un bloque comprende desde el lugar de la declaración hasta el final de ese bloque.
Reglas de ámbito: variables • Las variables externas se definen una sola vez fuera de todas las funciones y, si esta definición no precede a la definición de la función que la utiliza, la función tiene que incluir una declaración externa (con la palabra clave extern) de esta variable. • Si una variable local y una variable global tienen el mismo nombre, todas las referencias a ese nombre dentro del ámbito de la variable local se refieren a la variable local.
Reglas de ámbito: variables • Variables estáticas externas: • sólo pueden ser referenciadas en el resto del fichero en el que se definen (no desde el resto de ficheros que forman el programa). • Variables estáticas internas: • sólo pueden ser referenciadas en el interior del bloque en el que se definen, pero conservan su valor entre ejecuciones sucesivas del bloque.
Recursión • Cuando durante la ejecución de una función se realiza una invocación de esa misma función, se dice que se produce una llamada recursiva. • La recursión puede ser de dos tipos: • recursión propia: la función se invoca explícitamente a sí misma. • recursión mutua: la función llama a otra función que directa o indirectamente la invoca.
Recursión • Las soluciones no recursivas son en general más eficientes, en términos de espacio de almacenamiento y tiempo de ejecución, que las recursivas. • Cada vez que se invoca a una función se crea un nuevo juego de variables automáticas, y se las inicializa con el valor de los correspondientes parámetros formales.
Recursión • Hay muchos casos en que el modo más natural de describir un proceso es mediante una formulación recursiva (p.e. manipulación de árboles). • Una función recursiva tiene que contener una sentencia condicional en una de cuyas ramas termina la recursión (no contiene una llamada recursiva).
Preprocesador de C • En el código fuente se puede incluir una serie de instrucciones especiales que no pertenecen al lenguaje en sí y que facilitan el desarrollo de los programas. • Las instrucciones se denominan directivas, y se procesan al principio de la compilación del programa con el preprocesador. fich.c Preprocesador fich.i Compilador fich.o
Preprocesador de C • Las directivas del preprocesador pueden aparecer en cualquier parte del programa, pero sólo tendrán efecto en la porción del programa que sigue a su aparición. • Toda aquella línea que comience con # es una directiva del preprocesador; la sintaxis de estas directivas es independiente del resto del lenguaje. • Por convenio se utilizan letras mayúsculas para los nombres definidos en las directivas, p.e. # define TAM-MAX 100
Preprocesador de Cmacros • Una macro define un texto que ha de insertarse en el fichero fuente de un programa durante su compilación. • El texto que se ha de insertar puede depender de los parámetros de la macro.
Preprocesador de Cmacros sin parámetros • #define: se utiliza para definir un identificador junto con una secuencia de caracteres que se pondrán en lugar del identificador cada vez que este aparezca en el fichero fuente. Su sintaxis es: #definenombre_macrocadena • No forman parte de cadena los blancos localizados entre nombre_macro y el primer token y entre el último token y el salto de línea.
Preprocesador de Cmacros sin parámetros • Si la cadena no cabe en una sola línea se continúa en la siguiente, después de escribirse la barra invertida \. • Provoca que el procesador sustituya las apariciones de nombre_macro por la cadena de caracteres que le siguen. • La sustitución no se lleva a cabo dentro de constantes carácter o cadena de caracteres.
Preprocesador de Cmacros con parámetros • La sintaxis de una macro que tiene argumentos es: #define nombre_macro(id1, …,idn) cadena • Las siguientes apariciones (“llamadas” a la macro) de nombre_macro(lista_de_cadenas_de_caracteres) se sustituyen por la cadena cadena. • Cada parámetro formal especificado en la definición se sustituye en cadena por el correspondiente parámetro actual de la “llamada” a la macro.
Preprocesador de Cmacros con parámetros • No puede haber ningún espacio entre nombre_macro y el paréntesis. • Los números de parámetros actuales y formales deben coincidir. • Los parámetros actuales se separan en la llamada a la macro mediante comas. • Una macro no se puede pasar a una función como parámetro. • Una macro no puede llamarse a sí misma recursivamente.
Preprocesador de Cmacros con parámetros, advertencias • Se debe encerrar entre paréntesis cada aparición de los parámetros en la definición de la macro. • Se debe encerrar toda la definición de la macro entre paréntesis. • Hay que tener cuidado con el número de veces que se evalúan los parámetros formales.
Preprocesador de Cmacros o funciones • Ventajas (de macros) • son más rápidas que las llamadas a funciones. • dado que sólo realizan sustituciones de texto, la misma macro puede servir para cualquier tipo de datos. • se puede pasar el nombre de un tipo como parámetro • Desventajas (de macros) • ocupan más espacio que las funciones, ya que una macro se puede insertar varias veces en el código • su sintaxis es más delicada que la de las funciones.
Preprocesador de Celiminación de definiciones • Se puede hacer que una macro deje de estar definida en el preprocesador como sigue: # undefnombre_macro
Preprocesador de Cinclusión de ficheros • Esta directiva provoca que el compilador pase a compilar el fichero cuyo nombre se especifica y cuando finalice continúe con la siguiente línea del fichero actual. Su sintaxis es: # include“nombre_fichero ” # include<nombre_fichero > • Se admite que los ficheros incluidos tengan, a su vez, directivas # include. • Esta directiva permite que varios ficheros fuente que forman parte del mismo programa compartan las mismas declaraciones
Preprocesador de Ccompilación condicional • Estas directivas permiten compilar selectivamente partes del código fuente del programa. • Si la expresión constante es cierta (se evalúa a un valor distinto de cero) se compila la lista de sentencias, en caso contrario, no se compila. # ifexpresión_constante lista-sentencias # endif
Preprocesador de Ccompilación condicional • Si la expresión constante es cierta (distinta de cero) se compila la primera lista de sentencias, si es falsa, se compila la segunda lista de sentencias. # ifexpresión_constante lista_sentencias_1 # else lista_sentencias_2 # endif
Preprocesador de Ccompilación condicional • Se evalúan las expresiones constantes en el orden en que aparecen. Cuando una expresión sea cierta, se compilan las sentencias correspondientes y se sigue compilando la siguiente línea tras #endif. # ifexpresión_constante1 lista_sentencias_1 # elifexpresión_constante2 lista_sentencias_2 ... # else lista_sentencias # endif
Preprocesador de Ccompilación condicional • Otra directiva de compilación condicional es ifdef • Si el nombre de la macro está definido previamente para el procesador (mediante #define), se compilan las sentencias, si no está definido no se compilan. # ifdefidentificador lista_sentencias # endif • Puede utilizarse en combinación con la directiva #else
Preprocesador de Ccompilación condicional • La directiva “inversa” a ifdef es ifndef • Si el nombre de la macro no está definido previamente para el procesador, se compilan las sentencias, si está definido no se compilan. # ifndefidentificador lista_sentencias # endif • Puede utilizarse en combinación con la directiva #else