Search code examples
cfunctionargumentsparameter-passingvariadic-functions

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


I read here that in C void foo() means a function foo taking an unspecified number of arguments of unspecified type.

Can anyone give me or point me to an example where a C function takes an unspecified number of arguments? What can this be applied to in C? I couldn't find anything on the web.


Solution

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