Tengo una biblioteca que creé,
Expediente milib.c:
#include <mylib.h>
int
testlib() {
printf("Hello, World!\n");
return (0);
}
Expediente milib.h:
#include <stdio.h>
extern int testlib();
En mi programa, he intentado llamar a esta función de biblioteca:
Expediente miprograma.c:
#include <mylib.h>
int
main (int argc, char *argv[]) {
testlib();
return (0);
}
Cuando intento compilar este programa me sale el siguiente error:
In file included from myprogram.c:1
mylib.h:2 warning: function declaration isn't a prototype
Estoy usando: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
¿Cuál es la forma correcta de declarar un prototipo de función?
C ª int foo()
y int foo(void)
son funciones diferentes. int foo()
acepta un número arbitrario de argumentos, mientras que int foo(void)
acepta 0 argumentos. En C++ significan lo mismo. Te sugiero que uses void
consistentemente cuando te refieres a que no hay argumentos.
Si tienes una variable a
, extern int a;
es una manera de decirle al compilador que a
es un símbolo que podría estar presente en una unidad de traducción diferente (el compilador de C habla del archivo fuente), no lo resuelva hasta el momento del enlace. Por otro lado, los símbolos que son nombres de funciones se resuelven de todos modos en el momento del enlace. El significado de un especificador de clase de almacenamiento en una función (extern
, static
) sólo afecta a su visibilidad y extern
es el valor predeterminado, por lo que extern
en realidad es innecesario.
Sugiero quitar el extern
es extraño y generalmente se omite.
Respuesta rápida: cambiar int testlib()
para int testlib(void)
para especificar que la función no toma argumentos.
A prototipo es, por definición, una declaración de función que especifica el tipo o los argumentos de la función.
Una declaración de función no prototipo como
int foo();
es una declaración de estilo antiguo que no especifica el número o tipos de argumentos. (Antes del estándar ANSI C de 1989, este era el único tipo de declaración de función disponible en el lenguaje). Puede llamar a una función de este tipo con cualquier número arbitrario de argumentos, y el compilador no está obligado a quejarse, pero si el la llamada es inconsistente con el definiciónsu programa tiene un comportamiento indefinido.
Para una función que toma uno o más argumentos, puede especificar el tipo de cada argumento en la declaración:
int bar(int x, double y);
Las funciones sin argumentos son un caso especial. Lógicamente, los paréntesis vacíos habrían sido una buena forma de especificar que una función no acepta argumentos, pero esa sintaxis ya estaba en uso para las declaraciones de funciones de estilo antiguo, por lo que el comité ANSI C inventó una nueva sintaxis usando el void
palabra clave:
int foo(void); /* foo takes no arguments */
Una función definición (que incluye código para lo que realmente hace la función) también proporciona una declaración. En tu caso, tienes algo similar a:
int testlib()
{
/* code that implements testlib */
}
Esto proporciona una declaración de no prototipo para testlib
. Como definición, esto le dice al compilador que testlib
no tiene parámetros, pero como declaración, solo le dice al compilador que testlib
toma un número y tipo(s) de argumentos no especificados pero fijos.
si cambias ()
para (void)
la declaración se convierte en un prototipo.
La ventaja de un prototipo es que si accidentalmente llamas testlib
con uno o más argumentos, el compilador diagnosticará el error.
(C++ tiene reglas ligeramente diferentes. C++ no tiene declaraciones de función de estilo antiguo, y los paréntesis vacíos significan específicamente que una función no acepta argumentos. C++ admite el (void)
sintaxis para mantener la coherencia con C. Pero, a menos que necesite específicamente que su código compile tanto como C como C++, probablemente debería usar la ()
en C++ y el (void)
sintaxis en C.)
Tratar:
extern int testlib(void);
Elimine extern de la declaración en mylib.h Especialmente si está escribiendo un programa C puro, la declaración extern no es necesaria allí.
– Ryan Ahearn
3 de septiembre de 2008 a las 17:16