TL; DR
In ads
void func1();
the behavior is completely different. The first declares a function without any prototype - and any number of arguments may be required! While the latter declares a function with a prototype, which has no parameters and takes no arguments.
In the definitions
void func1() { }
and
void func2(void) { }
These two behave distinctly, while the C compiler should print a diagnostic message when calling a prototyped function with the wrong number of arguments, you do not need to do this when calling a function without a prototype.
Ie, given the above definitions
func1(1, 2, 3);
However, both calls are illegal in strictly consistent programs, since they are clearly undefined compared to 6.5.2.2p6 .
In addition, empty parentheses are considered an obsolete feature:
Using function declarators with empty brackets (not prototype parameter type declarators) is an obsolete function.
and
Using function definitions with separate parameter identifiers and declaration lists (rather than the type and type of the prototype identifier) is an obsolete function.
More details
There are 2 interrelated but different concepts: parameters and arguments.
In the following passage:
int foo(int n, char c) { ... } ... foo(42, ch);
n and c are parameters. 42 and ch are arguments.
The above excerpt applies only to function parameters, but does not say anything about the prototype or function arguments.
The declaration void func1() means that the function func1 can be called with any number of arguments , that is, information about the number of arguments is not specified (as a separate declaration, C99 indicates this as a “function without parameter specification”, whereas the declaration void func2(void) means the func2 function does not accept any arguments at all.
The quote in your question means that in the definition of the function , void func1() and void func2(void) both signal to them that there are no parameters, that is, the names of the variables that are set to the values of the arguments when the function is introduced. void func() {} contrasts with void func(); , the first of them states that func does not really accept any parameters, while the latter is an declaration for the func function, for which neither parameters nor their types are specified (declaration without prototype).
However, they do differ by definition in that
The definition of void func1() {} does not declare a prototype, whereas void func2(void) {} does because () not a list of parameter types, whereas (void) is a list of parameter types ( 6.7.5.3.10 ):
A special case of an unnamed parameter of type void as the only element in the list indicates that the function has no parameters.
and further 6.9.1.7
If the declarator contains a list of parameter types, list also defines the types of all parameters; such a declarator also serves as a prototype of the function for subsequent calls to the same function in the same translation system. If the declarator contains a list of identifiers, parameter types must be declared in the following declaration list. In any case, the type of each parameter is configured as described in 6.7.5.3 for the list of parameter types; the resulting type must be an object type.
The function definition declaration for func1 does not contain a list of parameter types , and therefore the function does not have a prototype.
void func1() { ... } can still be called with any number of arguments, while a compile-time error causes void func2(void) { ... } with any arguments (6.5.2.2):
If the expression that denotes the called function is of a type that includes the prototype , the number of arguments must match the number of parameters. Each argument must be of a type so that its value can be assigned to an object with an unqualified version of the type of its corresponding parameter.
(emphasis mine)
This is a limitation that, according to the standard, indicates that the corresponding implementation should display at least one diagnostic message about this problem. But since func1 does not have a prototype, an appropriate implementation is not required for any diagnosis.
However, if the number of arguments is not equal to the number of parameters, the behavior is undefined 6.5.2.2p6 :
If the expression that denotes the called function is of a type that does not include the prototype , [...] If the number of arguments is not equal to the number of parameters, the behavior is undefined.
Therefore, the theoretically compatible C99 compiler also makes an error or warning diagnosis in this case. Using StoryTeller provides evidence that clang can diagnose this ; however, my GCC does not seem to do this (and this might also require compatibility with some old obscure code):
void test() { } void test2(void) { } int main(void) { test(1, 2); test2(1, 2); }
When the above program is compiled with gcc -std=c99 test.c -Wall -Werror , the output is:
test.c: In function 'main': test.c:7:5: error: too many arguments to function 'test2' test2(1, 2); ^~~~~ test.c:3:6: note: declared here void test2(void) { } ^~~~~
That is, the arguments are not checked at all by the parameters of the function whose declaration in the definition is not prototyped ( test ), while GCC considers it a compilation error to indicate any arguments to the prototyped function ( test2 ); any appropriate implementation should diagnose this because it is a violation of the constraint.