¿Debe declarar el prototipo de función en C? [duplicar]
Soy un poco nuevo en C (tengo experiencia previa en Java, C# y algo de C++). En C, ¿es necesario declarar un prototipo de función o el código se puede compilar sin él? ¿Es una buena práctica de programación hacerlo? ¿O simplemente depende del compilador? (Estoy ejecutando Ubuntu 9.10 y usando el compilador GNU C, o gcc, en el IDE Code::Blocks)
Nunca es necesario declarar un prototipo para una función en C, ni en el C "antiguo" (incluido C89/90) ni en el nuevo C (C99). Sin embargo, existe una diferencia significativa entre C89/90 y C99 con respecto a las declaraciones de funciones.
En C89/90 no era necesario declarar ninguna función. Si la función no se declara en el momento de la llamada, el compilador "adivina" (infiere) la declaración implícitamente a partir de los tipos de argumentos pasados en la llamada y asume que el tipo de retorno es int
.
Por ejemplo
int main() {
int i = foo(5);
/* No declaration for `foo`, no prototype for `foo`.
Will work in C89/90. Assumes `int foo(int)` */
return 0;
}
int foo(int i) {
return i;
}
En C99, cada función que llame debe declararse antes del punto de llamada. Sin embargo, todavía no es necesario declararlo específicamente con un prototipo . Una declaración que no sea un prototipo también funcionará. Esto significa que en C99 la int
regla "implícita" ya no funciona (para tipos de retorno de funciones inferidas, en este caso), pero los tipos de parámetros aún se pueden adivinar a partir de los tipos de argumentos si la función se declara sin un prototipo.
El ejemplo anterior no se compilará en C99, ya que foo
no se declara en el momento de la llamada. Sin embargo, puedes agregar una declaración que no sea un prototipo.
int foo(); /* Declares `foo`, but still no prototype */
int main() {
int i = foo(5);
/* No prototype for `foo`, although return type is known.
Will work in C99. Assumes `int foo(int)` */
return 0;
}
...
y terminar con el código C99 válido.
Sin embargo, siempre es una buena práctica declarar un prototipo para la función antes de llamarla.
Una nota adicional: dije anteriormente que nunca es necesario declarar un prototipo de función. De hecho, para algunas funciones es un requisito. Para llamar correctamente una función variada en C ( printf
por ejemplo), la función debe declararse con un prototipo antes del punto de llamada. De lo contrario, el comportamiento no está definido. Esto se aplica tanto al C89/90 como al C99.
En ANSI C (es decir, C89 o C90), no es necesario declarar un prototipo de función; sin embargo, es una buena práctica utilizarlos. La única razón por la que el estándar le permite no usarlos es por compatibilidad con códigos muy antiguos.
Si no tiene un prototipo y llama a una función, el compilador inferirá un prototipo a partir de los parámetros que pase a la función. Si declara la función más adelante en la misma unidad de compilación, obtendrá un error de compilación si la firma de la función es diferente de lo que supuso el compilador.
Peor aún, si la función está en otra unidad de compilación, no hay forma de obtener un error de compilación, ya que sin un prototipo no hay forma de verificarlo. En ese caso, si el compilador se equivoca, podría obtener un comportamiento indefinido si la llamada a la función envía tipos diferentes a los que espera la función en la pila.
La convención es declarar siempre un prototipo en un archivo de encabezado que tenga el mismo nombre que el archivo fuente que contiene la función.
En C99 o C11, el estándar C requiere una declaración de función dentro del alcance antes de llamar a cualquier función. Muchos compiladores no imponen esta restricción en la práctica a menos que usted los obligue a hacerlo.