c - img - meta alt tag
DeclaraciĆ³n de funciĆ³n: K & R vs ANSI (3)
La sintaxis de K & R es obsoleta, puedes omitirla a menos que tengas que mantener un código muy antiguo.
// K&R syntax
int foo(a, p)
int a;
char *p;
{
return 0;
}
// ANSI syntax
int foo(int a, char *p)
{
return 0;
}
Esta pregunta ya tiene una respuesta aquí:
¿Cuáles son las diferencias entre una declaración de función K & R y una declaración de función ANSI?
Solo quiero agregar que en los modificadores de tipo de estilo K & R tradicionales para funciones que devuelven un valor int
ni siquiera son necesarias.
Considere la notación C11 moderna de un programa HelloWorld simple:
int main(int argc, char **argv) {
printf("hello world/n");
return 0;
}
Esto es equivalente al estilo de notación K & R:
main(argc, argv)
int argc;
char **argv;
{
printf("hello world/n");
return 0;
}
Tenga en cuenta que se ignora el int
ante main()
, pero el código aún se compila. Eso es parte de la definición de K & R.
Cita Wikipedia:
En las primeras versiones de C, solo las funciones que devolvían un valor no int debían declararse si se usaban antes de la definición de la función; se asumió que una función utilizada sin ninguna declaración previa devuelve el tipo int, si se usó su valor.
--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
Podría decirse que este es un estilo de codificación heredado y debe evitarse debido a cuestiones de claridad, pero con bastante frecuencia los viejos libros de texto de algoritmos favorecen este tipo de estilo de K & R.
Legacy K & R-Style Declarations / Definitions
Cuando Kernighan y Ritchie publicaron por primera vez "The C Programming Language", C aún no ofrecía prototipos de funciones completas. Existían declaraciones de funciones hacia adelante, pero con el único propósito de indicar un tipo de devolución. Para las funciones que devolvieron int
, no fueron necesarias hasta C99.
Por C89, se ha agregado la noción de un prototipo de función, que también especifica los tipos de los parámetros (e, implícitamente, su número). Dado que un prototipo es también un tipo de declaración de función, el término no oficial "declaración de función de K & R" se usa a veces para una declaración de función que no es también un prototipo.
// K&R declarations, we don''t know whether these functions have parameters.
int foo(); // this declaration not strictly necessary until C99, because it returns int
float bar();
// Full prototypes, specifying the number and types of parameters
int foo(int);
float bar(int, float);
// K&R definition of a function
int foo(a)
int a; // parameter types were declared separately
{
// ...
return 0;
}
// Modern definition of a function
float bar(int a, float b)
{
// ...
return 0.0;
}
La declaración accidental de K & R
Vale la pena señalar que los recién llegados a C pueden usar accidentalmente declaraciones de K & R cuando pretendan usar un prototipo completo, porque es posible que no se den cuenta de que una lista de parámetros vacía debe especificarse como void
.
Si declaras y defines una función como
// Accidental K&R declaration
int baz(); // May be called with any possible set of parameters
// Definition
int baz() // No actual parameters means undefined behavior if called with parameters.
// Missing "void" in the parameter list of a definition is undesirable but not
// strictly an error, no parameters in a definition does mean no parameters;
// still, it''s better to be in the habit of consistently using "void" for empty
// parameter lists in C, so we don''t forget when writing prototypes.
{
// ...
return 0;
}
... entonces en realidad no ha dado un prototipo para una función que no toma parámetros, sino una declaración en estilo K & R para una función que acepta un número desconocido de parámetros de tipo desconocido.
AnT señala en esta respuesta a una pregunta similar que esta sintaxis es obsoleta pero aún legal a partir de C99 (y que los indicadores de función para funciones con un número desconocido y tipo de parámetros todavía tienen aplicaciones potenciales, aunque con un alto riesgo de comportamiento indefinido); como tal, los compiladores compatibles, en el mejor de los casos, producirán una advertencia si se declara o se llama a una función sin un prototipo adecuado.
Llamar a funciones sin prototipos es menos seguro, porque el compilador no puede verificar que haya pasado el número correcto y los tipos de parámetros en el orden correcto; comportamiento indefinido si la llamada no es realmente correcta.
La forma correcta de declarar y definir una función sin parámetros es, por supuesto:
// Modern declaration of a parameterless function.
int qux(void); // "void" as a parameter type means there are no parameters.
// Without using "void", this would be a K&R declaration.
// Modern definition of a parameterless function
int qux(void)
{
// ...
return 0;
}