I'd like to know why the following code:
void foo(void);
void foo()
{
}
is valid in gcc. In C, there is no such thing as overloading and above declarations (in fact, one of them is a definition) declare two different functions (the first one doesn't take any arguments, the second one could take any number of arguments of any types).
However, if we provide a definition for the first function:
void foo(void)
{
}
void foo()
{
}
a compilation fails this time due to redefinition. But still, the first code is correct and might be confusing as in the following:
void foo(void);
int main(void)
{
foo(); //OK
//foo(5); //Wrong, despite ->the definition<- allows it
}
void foo()
{
}
On the other hand, something like this is invalid straightaway:
void foo(int);
void foo() //error: number of arguments doesn't match prototype
{
}
I think the compiler's behavior is kinda weird in comparison to my first foregoing code. int
isn't equal to (/*empty list*/)
and neither is void
.
Can anyone explain this ?
In computer programming, when void is used as a function return type, it indicates that the function does not return a value. When void appears in a pointer declaration, it specifies that the pointer is universal. When used in a function's parameter list, void indicates that the function takes no parameters.
For example, if the my_function() function, discussed in the previous section, requires two integer parameters, the declaration could be expressed as follows: return_type my_function(int x, y); where int x, y indicates that the function requires two parameters, both of which are integers.
To activate a void function with value parameters, we specify the name of the function and provide the actual arguments enclosed in parentheses. The order and types of the list of arguments should correspond exactly to those of the formal parameters declared in the function prototype.
The function body has three parts: an optional declarative part, an executable part, and an optional exception-handling part.
Quoting a late draft of the standard about function declarators:
(6.7.6.3/10) The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
(6.7.6.3/14) An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters.
So the declarators of the declaration and definition are in fact compatible, and thus refer to the same function (with no overloading taking place of course, as such a thing does not exist in C.)
The line below is a function declaration, which tells the signature of the function foo
: what is the type of the returned value and what are the types of the arguments.
void foo(void);
Below there is a function definition, which tells what does the function do. It does not overload anything. The definition and the declaration must match in the signature. void
data type allows omitting it in the function definition.
void foo()
{
}
Since void
is not an instantiable type (you cannot have a value of type void
) it is OK to omit the arguments in the signature of the function's definition. However, if you try to do:
void foo(void*);
void foo() {
}
then you'll have a compile error because foo
is expected to get a pointer to a don't-worry-about-type value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With