My book says that I should write a prototype of a procedure (that hasn't any parameters) like this: void test(void);
I usually write the prototype of a procedure that hasn't any parameters like this: void test();
and it works.
What is the difference between these 2 declarations?
In C, an empty parameter list in a function declaration means that the function takes an unspecified number of arguments - in a definition, it means it takes no arguments:
void foo(); // declaration, number of arguments is unspecified
void foo() // definition, number of arguments is zero
{
...
}
A parameter list of void
in both a declaration and a definition means the function takes no arguments:
void foo( void ); // declaration, number of arguments is 0
void foo( void ) // definition, number of arguments is 0
{
...
}
So why is this the case?
Neither prototype declaration syntax nor the void
keyword were originally part of C - there was no way to specify "this function doesn't return a value" and "this function takes this many arguments of this type". In the early Cretaceous, function definitions were written as
foo( a, b, c ) // return type of int assumed
T a; // for arbitrary types T, Q, R
Q b;
R c;
{
// do something interesting with a, b, and c
}
and the corresponding declaration was simply written as
foo(); // strictly not necessary, since the compiler would assume a return type of int
C originally had no mechanism to validate the number and types of arguments in a function call against a function declaration. If you called foo
as
foo( x, y, z, oops );
the compiler couldn't tell you that you'd passed too many arguments, or that any of x
, y
, or z
were the wrong type. You wouldn't know that there was a problem until runtime.
The 1989 standard introduced the void
keyword along with function prototype syntax, so you could now specify the number and types of parameters in a function declaration, allowing the compiler to catch mismatches like the above:
void foo( T, Q, R ); // only need to specify types in a declaration
void foo( T a, Q b, R c )
{
// do something interesting with a, b, c
}
and the void
keyword as a parameter list meant that the function took no parameters:
void foo( void );
Because legacy code is forever, old-style function definitions and declarations are still supported, although implicit int
typing no longer is. That's why you can still declare a function as void foo();
, although best practice is to declare it as void foo( void );
if it takes no arguments. Otherwise, if you try to call foo
with an argument like
foo( x );
the compiler will not be able to catch the mismatch.