Sintaxis de la función C, tipos de parámetros declarados después de la lista de parámetros

Soy relativamente nuevo en C. He encontrado una forma de syntax de función que nunca había visto antes, donde los tipos de parámetros se definen después de esa lista de parámetros. ¿Puede alguien explicarme cómo es diferente de la syntax típica de la función C?

Ejemplo:

int main (argc, argv) int argc; char *argv[]; { return(0); } 

Esa es la syntax antigua para las listas de parámetros, que todavía es compatible. En K & R C también podría dejar fuera de las declaraciones de tipo y se convertirían en int por defecto. es decir

 main(argc, argv) char *argv[]; { return 0; } 

sería la misma función.

Lo que también es interesante es la diferencia de convención de llamadas con funciones y funciones sin prototipo. Considere una antigua definición de estilo:

 void f(a) float a; { /* ... */ } 

En este caso, la convención de llamadas es que todos los argumentos se promueven antes de pasarse a la función. Entonces, si f recibe un double pero el parámetro tiene un tipo float (que es perfectamente válido), el comstackdor debe emitir un código que convierta el doble en un flotante antes de ejecutar el cuerpo de la función.

Si incluye un prototipo, el comstackdor ya no realiza más promociones automáticas y los datos pasados ​​se convierten a los tipos de los parámetros del prototipo como si fueran asignados. Por lo tanto, lo siguiente no es legal y da como resultado un comportamiento indefinido:

 void f(float a); void f(a) float a; { } 

En este caso, la definición de la función convertiría el parámetro presentado de double (la forma promovida) a float porque la definición es de estilo antiguo. Pero el parámetro se envió como un flotante, porque la función tiene un prototipo. Sus opciones para resolver las contradicciones son las dos siguientes:

 // option 1 void f(double a); void f(a) float a; { } // option 2 // this declaration can be put in a header, but is redundant in this case, // since the definition exposes a prototype already if both appear in a // translation unit prior to the call. void f(float a); void f(float a) { } 

La opción 2 debería ser preferible si tiene la opción, ya que elimina la antigua definición de estilo por adelantado. Si tales tipos de funciones contradictorias para una función aparecen en la misma unidad de traducción, el comstackdor generalmente le dirá (pero no es obligatorio). Si tales contradicciones aparecen en varias unidades de traducción, el error posiblemente pasará desapercibido y puede dar lugar a errores difíciles de predecir. Lo mejor es evitar estas definiciones de estilo antiguo.

Este es el estilo K & R de la persona que llama o la statement de estilo antiguo .

Tenga en cuenta que esta statement es significativamente diferente de la statement moderna. La statement K & R no introduce un prototipo para la función, lo que significa que no expone los tipos de los parámetros al código externo.

Si bien la syntax antigua para la definición de la función aún funciona (con advertencias, si le preguntas a tu comstackdor), su uso no proporciona prototipos de funciones.
Sin prototipos de función, el comstackdor no comprobará si las funciones se llaman correctamente.

 #include  int foo(c) int c; { return printf("%d\n", c); } int bar(x) double x; { return printf("%f\n", x); } int main(void) { foo(42); /* ok */ bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */ return 0; } 

Cuando se ejecuta el progtwig, la salida en mi máquina es

 $ gcc proto.c $ gcc -Wstrict-prototypes proto.c proto.c:4: warning: function declaration isn't a prototype proto.c:10: warning: function declaration isn't a prototype $ ./a.out 42 0.000000 

No hay diferencia, es solo que esa es la syntax antigua para las declaraciones de funciones en C: se utilizó antes de ANSI. Nunca escriba tal código a menos que planee dárselo a sus amigos de los años 80 . Además, nunca dependas de supuestos de tipo implícitos (como parece sugerir otra respuesta)

Es lo mismo pero a la vieja usanza. Probablemente descubras que se trata de un código antiguo heredado.