Declaración de función: K & R vs ANSI

¿Cuáles son las diferencias entre una statement de función K & R y una statement de función ANSI?

    La syntax 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; } 

    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 statement de función, el término no oficial “statement de función de K & R” se usa a veces para una statement 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 statement 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 statement 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 syntax 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 comstackdores 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 comstackdor 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; } 

    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 progtwig 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 comstack. 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 statement 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 encoding 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.