Two function declarations with void and empty argu

2019-04-28 17:37发布

问题:

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 ?

回答1:

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



回答2:

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.



回答3:

C Standard defines for void as:-

The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

And the definition

void foo()
{
}

implies that the parameters are empty set of values which is valid for definition,so the gcc allows.

Also prototype for function declaration specifies:-

The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.