Namespaces
Variants

Function definitions

From cppreference.net

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
1) Definición de función de estilo nuevo (C89). Esta definición introduce tanto la función en sí misma como sirve como prototipo de función para cualquier futura expresión de llamada a función , forzando conversiones de las expresiones de argumento a los tipos de parámetros declarados.
int max(int a, int b)
{
    return a>b?a:b;
}
double g(void)
{
    return 0.1;
}
2) (hasta C23) Definición de función al estilo antiguo (K&R). Esta definición no se comporta como un prototipo y cualquier futura expresión de llamada a función realizará promociones de argumentos predeterminadas.
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.

void f(char *s) { puts(s); } // el tipo de retorno es void
int sum(int a, int b) { return a+b; } // el tipo de retorno es int
int (*foo(const void *p))[3] { // el tipo de retorno es puntero a arreglo de 3 int
    return malloc(sizeof(int[3]));
}

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