Lo que también es interesante es la diferencia de convención de llamadas con funciones y funciones sin prototipo. Considere una vieja definición de estilo:
void f(a)
float a; {
/* ... */
}
En este caso, la convención de llamada es que todos los argumentos son promovidos antes de ser pasados a la función. Entonces, si f
recibe un double
pero el parámetro tiene el tipo float
(que es perfectamente válido) el compilador 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 compilador 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.Así que 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 sería convertir el parámetro enviado desde double
(la forma promovido) 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 de resolver las contradicciones son los 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) {
}
Opción 2 debe ser preferido si usted tiene la elección, ya que se deshace de la definición de estilo antiguo en la delantera. Si tales tipos de funciones contradictorias para una función aparecen en la misma unidad de traducción, el compilador 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.
Tanto C89/90 como C99 aún son oficialmente compatibles con las declaraciones de estilo de K & R. Sin embargo, en C99 todos los parámetros deben declararse explícitamente (ya no hay regla "implícita implícita"). – AnT
Odio llegar tarde a la fiesta (¿como 4 años después?), Pero ¿quiere decir que en C99 deben declararse explícitamente * en la lista de parámetros * o * en la función *? Por ejemplo, la regla int predeterminada: dado que ya no se predetermina a int, entonces sus tipos deben declararse en la función antes del uso ** if ** los tipos no se suministraron en la lista de parámetros? –
@ChrisCirefice Para responderle 4 años después: en C99, todos los parámetros deben declararse en la lista de parámetros. Las variables que se declaran en la función nunca han predeterminado a 'int', y por lo tanto deben declararse explícitamente. –