Unspecified number of parameters in C functions – void foo()

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).

Leave a Comment