与无效,空参数列表两个函数声明(Two function declarations with voi

2019-09-21 08:15发布

我想知道为什么下面的代码:

void foo(void);
void foo()
{
}

在GCC有效。 在C中,没有这样的东西作为重载和上面的声明(事实上,它们中的一个是一个定义)声明两个不同的功能(第一个不带任何参数,第二个可以采取任何数目的任何参数类型)。

然而,如果我们提供了第一个函数的定义:

void foo(void)
{
}
void foo()
{
}

编译失败,此时由于重新定义。 但尽管如此 ,第一个代码是正确的,可能是在下面的困惑:

void foo(void);

int main(void)
{
    foo();      //OK
    //foo(5);   //Wrong, despite ->the definition<- allows it
}

void foo()
{
}

在另一方面,这样的事情是无效通俗易懂:

void foo(int);
void foo() //error: number of arguments doesn't match prototype
{
}

我觉得编译器的行为相比,我的第一个前面的代码有点奇怪。 int不等于(/*empty list*/)和既不是void

任何人都可以解释一下吗?

Answer 1:

引述有关函数声明的标准的后期草案:

(6.7.6.3/10)型空隙作为列表的唯一项未命名的参数的特殊情况指定该功能没有参数。

(6.7.6.3/14)的标识符列表只声明函数的参数的标识符。 在一个函数声明是该函数的定义的一部分空列表指定的函数没有参数。

因此,声明和定义的声明符其实都是兼容的,从而指向同一个函数(不带超载发生,当然,因为这样的事情在C.不存在)



Answer 2:

下面这行是一个函数声明,它告诉函数的签名foo :什么是返回值的类型和什么类型的参数。

void foo(void);

下面有一个函数的定义,它告诉什么是功能做。 它不超载什么。 定义和声明必须在签名匹配。 void数据类型允许在函数定义忽略它。

void foo()
{
}

由于void不是实例化的类型(你不能有类型的值void ),它是确定省略参数的函数定义的签名。 但是,如果你尝试这样做:

void foo(void*);
void foo() {
}

然后,因为你有一个编译错误foo有望获得一个指向鸵鸟政策后顾之忧的有关类型值。



Answer 3:

C标准定义了空隙为: -

空隙类型包括一个空的一组值; 这是一个不完整的类型无法完成。

和定义

void foo()
{
}

意味着参数是空集,其是有效的定义的值,所以在gcc允许。

还原型函数声明指定: -

void类型在列表中唯一的项目未命名参数的特殊情况,指出这个函数没有参数。



文章来源: Two function declarations with void and empty argument list