Empty parentheses are part of an old C grammar for function declarations that did not provide type checking. Prior to the creation of parameter lists with types, function definitions had a form like this:
int foo(a, b, c)
char a;
int *b;
float c;
{
// body of function
}
Then function declarations that were not definitions would just use ()
, as in int foo();
. So a function definition would show what arguments a function expected, including the number of them and their types, but a declaration would not.
Of course, function definitions are often not visible when compiling a source file, as the definitions are in other files, although of course a declaration may be provided, often in header files. So, when a function is called, the compiler would not generally see the definition and would not generally know what arguments the function required. So it could not check the arguments. Thus, there is no requirement that the compiler provide a diagnostic message for a mismatch with functions declared with this old grammar.
The programmer is responsible for making the arguments match. The function definition does specify how many parameters the function has and does specify their types, and the C standard does not define the behavior if there is a mismatch. But that is a run-time issue; it is not something the compiler is required to diagnose, and it is not something the compiler can diagnose if the function definition is not visible to it.
When the definition is visible, the compiler could issue a diagnostic, especially if the definition appears prior to the call. Although GCC does not diagnose this, Clang does, if the definition appears first. So this is a missed opportunity for the GCC developers.
When the grammar for function prototypes (function declarations with types for the parameters) was created, ()
could not be used to indicate the function had no parameters, since it was already in use for the old grammar. So the notation (void)
was invented for this; to declare, outside of a definition, that a function takes no parameters, you muse use (void)
, as in int foo(void);
. This may also be used in a function definition, int foo(void) { … }
.
When a function declaration has this new form, the compiler is required to check the number and types of arguments in a call to the function and to issue a diagnostic if there is a mismatch.