That's an old-style function declaration.
This declaration:
void foo();
declares that foo
is a function returning void
that takes an unspecified but fixed number and type(s) of arguments. It doesn't mean that calls with arbitrary arguments are valid; it means that the compiler can't diagnose incorrect calls with the wrong number or type of arguments.
Somewhere, perhaps in another translation unit (source file), there has to be a definition of the function, perhaps:
void foo(x, y)
long x;
double *y;
{
/* ... */
}
This means that any call to foo
that doesn't pass two arguments of type long
and double*
is invalid, and has undefined behavior.
Prior to the 1989 ANSI C standard, these were the only kind of function declaration and definition available in the language, and the burden of writing correct function calls was entirely on the programmer. ANSI C added prototypes, function declarations that specify the types of a function's parameters, which allow compile-time checking of function calls. (This feature was borrowed from early C++.) The modern equivalent of the above would be:
void foo(long x, double *y);
/* ... */
void foo(long x, double *y) {
/* ... */
}
Old-style (non-prototype) declarations and definitions are still legal, but they're officially obsolescent, which means that, in principle, they could be removed from a future version of the language -- though since they're still around in the 2011 standard I don't know that that will ever actually happen.
There is no good reason to use old-style function declarations and definitions in modern C code. (I've seen arguments for using them in some corner cases, but I find them unconvincing.)
C also supports variadic functions like printf
, which do take an arbitrary number of arguments, but that's a distinct feature. A variadic function must be declared with a prototype, which includes a trailing , ...
. (Calling a variadic function with no visible prototype isn't illegal, but it has undefined behavior.) The function itself uses macros defined in <stdarg.h>
to process its parameters. As with old-style function declarations, there is no compile-time checking for arguments corresponding to the , ...
(though some compilers may check some calls; for example gcc warns if the arguments in a printf
call are inconsistent with the format string).