Function definitions
Una definición de función asocia el cuerpo de la función (una secuencia de declaraciones y sentencias) con el nombre de la función y la lista de parámetros. A diferencia de declaración de función , las definiciones de función solo están permitidas en el ámbito de archivo (no hay funciones anidadas).
C admite dos formas diferentes de definiciones de función:
| attr-spec-seq (opcional) specifiers-and-qualifiers parameter-list-declarator function-body | (1) | ||||||||
| specifiers-and-qualifiers identifier-list-declarator declaration-list function-body | (2) | (hasta C23) | |||||||
donde
| attr-spec-seq | - | (C23) una lista opcional de atributos , aplicados a la función |
| specifiers-and-qualifiers | - |
una combinación de
|
| parameter-list-declarator | - | un declarador para un tipo de función que utiliza una lista de parámetros para designar parámetros de función |
| identifier-list-declarator | - | un declarador para un tipo de función que utiliza una lista de identificadores para designar parámetros de función |
| declaration-list | - | secuencia de declaraciones que declaran cada identificador en identifier-list-declarator . Estas declaraciones no pueden usar inicializadores y el único especificador de clase de almacenamiento permitido es register . |
| function-body | - | una sentencia compuesta , es decir, una secuencia de declaraciones y sentencias entre llaves, que se ejecuta cada vez que se llama a esta función |
int max(int a, int b) { return a>b?a:b; } double g(void) { return 0.1; }
int max(a, b) int a, b; { return a>b?a:b; } double g() { return 0.1; }
Contenidos |
Explicación
Al igual que con las declaraciones de funciones , el tipo de retorno de la función, determinado por el especificador de tipo en specifiers-and-qualifiers y posiblemente modificado por el declarator como es habitual en las declaraciones , debe ser un tipo de objeto completo no array o el tipo void . Si el tipo de retorno fuera cvr-cualificado, se ajusta a su versión no cualificada para el propósito de construir el tipo de función.
Al igual que con las declaraciones de funciones , los tipos de los parámetros se ajustan de funciones a punteros y de arrays a punteros para construir el tipo de función, y los calificadores cvr de nivel superior de todos los tipos de parámetros se ignoran para determinar el tipo de función compatible .
|
A diferencia de las declaraciones de función , no se permiten parámetros formales sin nombre (de lo contrario, habría conflictos en las definiciones de función al estilo antiguo (K&R)), deben tener nombre incluso si no se utilizan dentro de la función. La única excepción es la lista de parámetros especial ( void ) . |
(hasta C23) |
|
Los parámetros formales pueden no tener nombre en las definiciones de función, ya que las definiciones de función al estilo antiguo (K&R) han sido eliminadas. Los parámetros sin nombre son inaccesibles por nombre dentro del cuerpo de la función. |
(desde C23) |
int f(int, int); // declaración // int f(int, int) { return 7; } // Error hasta C23, OK desde C23 int f(int a, int b) { return 7; } // definición int g(void) { return 8; } // OK: void no declara un parámetro
Dentro del cuerpo de la función, cada parámetro con nombre es una expresión lvalue , tienen duración de almacenamiento automática y ámbito de bloque . La disposición de los parámetros en memoria (o si se almacenan en memoria) no está especificada: es parte de la convención de llamada .
int main(int ac, char **av) { ac = 2; // los parámetros son lvalues av = (char *[]){"abc", "def", NULL}; f(ac, av); }
Consulte function call operator para otros detalles sobre la mecánica de una llamada a función y return para regresar desde funciones.
__func__Dentro de cada cuerpo-de-función , la variable predefinida especial __func__ con ámbito de bloque y duración de almacenamiento estático está disponible, como si se definiera inmediatamente después de la llave de apertura mediante static const char __func__[] = "function name"; Este identificador especial se utiliza a veces en combinación con las constantes de macro predefinidas __FILE__ y __LINE__ , por ejemplo, mediante assert . |
(desde C99) |
Notas
La lista de argumentos debe estar explícitamente presente en el declarador, no puede heredarse de un typedef
typedef int p(int q, int r); // p es un tipo de función int(int, int) p f { return q + r; } // Error
|
En C89, specifiers-and-qualifiers era opcional, y si se omitía, el tipo de retorno de la función por defecto era int (posiblemente modificado por el declarator ). Además, la definición al estilo antiguo no requería una declaración para cada parámetro en declaration-list . Cualquier parámetro cuya declaración faltaba tenía tipo int max(a, b) // a and b have type int, return type is int { return a>b?a:b; } |
(hasta C99) |
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| DR 423 | C89 | el tipo de retorno podría estar calificado | el tipo de retorno está implícitamente descalificado |
Referencias
- Estándar C17 (ISO/IEC 9899:2018):
-
- 6.9.1 Definiciones de funciones (p: 113-115)
- Estándar C11 (ISO/IEC 9899:2011):
-
- 6.9.1 Definiciones de función (p: 156-158)
- Estándar C99 (ISO/IEC 9899:1999):
-
- 6.9.1 Definiciones de función (p: 141-143)
- Estándar C89/C90 (ISO/IEC 9899:1990):
-
- 3.7.1 Definiciones de función
Véase también
|
Documentación de C++
para
Definición de función
|