Definición de una función:
La forma general de una definición de función en lenguaje de programación C es la siguiente:
return_type function_name (lista de parámetros) { cuerpo de la función }
Una definición de función en lenguaje de programación C consiste en un encabezado de función y un cuerpo de función . Aquí están todas las partes de una función:
- Tipo de retorno : una función puede devolver un valor. Return_type es el tipo de datos del valor que devuelve la función. Algunas funciones realizan las operaciones deseadas sin devolver un valor. En este caso, return_type es la palabra clave void.
- Nombre de la función : este es el nombre real de la función. El nombre de la función y la lista de parámetros juntos constituyen la firma de la función.
- Parámetros : un parámetro es como un marcador de posición. Cuando se invoca una función, pasa un valor al parámetro. Este valor se conoce como parámetro o argumento real. La lista de parámetros se refiere al tipo, orden y número de parámetros de una función. Los parámetros son opcionales; es decir, una función puede no contener parámetros.
- Cuerpo de la función : El cuerpo de la función contiene una colección de declaraciones que definen lo que hace la función.
Funciones dentro de funciones (funciones anidadas)
Una función anidada es una función definida dentro de otra función. Las funciones anidadas son compatibles como una extensión en GNU C.
El nombre de la función anidada es local para el bloque donde se define. Por ejemplo, aquí definimos una función anidada llamada cuadrado, y la llamamos dos veces:
foo (doble a, doble b) { doble cuadrado (doble z) {return z * z; } cuadrado de retorno (a) + cuadrado (b); }
La función anidada puede acceder a todas las variables de la función que contiene que son visibles en el punto de su definición. Esto se llama alcance léxico. Por ejemplo, aquí mostramos una función anidada que usa una variable heredada llamada offset:
- ¿Cuáles son las funciones / gráficas matemáticas más comunes y básicas empleadas en economía?
- ¿Por qué son importantes los espacios [matemáticos] L ^ p [/ matemáticos]?
- Cuando se muestra que [math] -div [/ math] está junto a [math] \ nabla [/ math], ¿por qué consideramos [math] \ langle \ nabla f, X \ rangle = – \ langle f, div (X ) \ rangle [/ math] ([math] X [/ math] es un campo vectorial)?
- ¿Qué pasaría con f (x) si lo transformaras como y = f (1 / x)?
- ¿Qué es una función biyectiva?
bar (int * array, int offset, int size) { acceso int (int * array, int index) {matriz de retorno [índice + desplazamiento]; } int i; / * ... * / para (i = 0; i <tamaño; i ++) / * ... * / access (array, i) / * ... * / }
Las definiciones de funciones anidadas están permitidas dentro de las funciones en los lugares donde se permiten definiciones de variables; es decir, en cualquier bloque, mezclado con las otras declaraciones y declaraciones en el bloque.
Es posible llamar a la función anidada desde fuera del alcance de su nombre almacenando su dirección o pasando la dirección a otra función:
piratear (int * array, int size) { tienda vacía (int int, int value) {matriz [índice] = valor; } intermedio (tienda, tamaño); }
Aquí, la función intermedia recibe la dirección de la tienda como argumento. Si las llamadas intermedias se almacenan, los argumentos dados para almacenar se usan para almacenar en una matriz. Pero esta técnica funciona solo mientras la función de contención (hack, en este ejemplo) no salga.
Si intenta llamar a la función anidada a través de su dirección después de que salga la función que lo contiene, se desata el infierno. Si intenta llamarlo después de que salga un nivel de alcance que lo contiene, y si se refiere a algunas de las variables que ya no están en el alcance, puede tener suerte, pero no es prudente correr el riesgo. Sin embargo, si la función anidada no se refiere a nada que se ha salido del alcance, debe estar seguro.
GCC implementa tomar la dirección de una función anidada usando una técnica llamada trampolines. Esta técnica se describió en Lexical Closures for C ++ (Thomas M. Breuel, USENIX C ++ Conference Proceedings, 17-21 de octubre de 1988).
Una función anidada puede saltar a una etiqueta heredada de una función que lo contiene, siempre que la etiqueta se declare explícitamente en la función que lo contiene (ver Etiquetas locales). Tal salto regresa instantáneamente a la función que contiene, saliendo de la función anidada que hizo el goto y cualquier función intermedia también. Aquí hay un ejemplo:
bar (int * array, int offset, int size) {__label__ failure; int acceso (int * array, int index) {if (index> size) goto failure; matriz de retorno [índice + desplazamiento]; } int i; / * ... * / for (i = 0; i <size; i ++) / * ... * / access (array, i) / * ... * / / * ... * / return 0; / * El control viene aquí del acceso si detecta un error. * / fallo: retorno -1; }
Una función anidada siempre no tiene vinculación. Declarar uno con externo o estático es erróneo. Si necesita declarar la función anidada antes de su definición, use auto (que de otro modo no tiene sentido para las declaraciones de función).
bar (int * array, int offset, int size) { __etiqueta__ falla; acceso int automático (int *, int); / * ... * / acceso int (int * array, int index) { if (índice> tamaño) goto fracaso matriz de retorno [índice + desplazamiento]; } / * ... * / }
Referencia:
Usando la colección del compilador GNU (GCC)