两个带有void和空参数列表的函数声明

Que*_*tin 6 c parameters function void

我想知道为什么以下代码:

void foo(void);
void foo()
{
}
Run Code Online (Sandbox Code Playgroud)

在gcc中有效.在C中,没有重载和上面的声明(事实上,其中一个是定义)声明两个不同的函数(第一个不接受任何参数,第二个可以接受任何数量的参数)类型).

但是,如果我们为第一个函数提供定义:

void foo(void)
{
}
void foo()
{
}
Run Code Online (Sandbox Code Playgroud)

由于重新定义,此次编译失败.但是,第一个代码仍然是正确的,可能会令人困惑,如下所示:

void foo(void);

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

void foo()
{
}
Run Code Online (Sandbox Code Playgroud)

另一方面,这样的事情是无效的:

void foo(int);
void foo() //error: number of arguments doesn't match prototype
{
}
Run Code Online (Sandbox Code Playgroud)

我认为与我的第一个前面的代码相比,编译器的行为有点奇怪.int是不等于(/*empty list*/),也不是void.

有谁能解释一下?

eq-*_*eq- 12

引用关于函数声明符的标准的晚期草稿:

(6.7.6.3/10)void类型的未命名参数作为列表中唯一项的特殊情况指定该函数没有参数.

(6.7.6.3/14)标识符列表仅声明函数参数的标识符.函数声明符中的空列表是该函数定义的一部分,指定该函数没有参数.

所以声明和定义的声明符实际上是兼容的,因此引用相同的函数(当然没有重载,因为C中不存在这样的事情)

  • 这就是答案:_函数声明符中的空列表是该函数的__definition__的一部分,指定该函数没有参数._.如果它是另一种方式,声明是`void foo();`和定义`void foo(void){}`,这将不成立.你的答案是唯一一个真正注意到这种差异的人.+1 (2认同)
  • @Quentin,似乎*不是*的情况.我对标准的解释说两者在函数内是相同的*但只有前者引入了一个函数原型.这与您之前描述的GCC行为兼容.然而,定义是*兼容的*(如我在答案中所述). (2认同)