为什么在有参数和没有参数的情况下声明相同的函数不会导致编译错误?

Why does declaring the same function both with and without parameters not cause compilation errors?

提问人:arye 提问时间:5/3/2023 最后编辑:Vlad from Moscowarye 更新时间:5/3/2023 访问量:154

问:

对于代码:

int hi(int);
int hi();
int main()
{
    hi(3);
}

我没有收到任何编译错误(调用;没有参数确实会得到编译错误)。hi()

我预计编译器会抱怨该函数已经以不同的方式声明。知道为什么会这样吗?

C 编译器警告 函数声明 整数提升

评论


答:

7赞 Some programmer dude 5/3/2023 #1

您可以根据需要多次声明相同的符号,只要声明不相互矛盾,就不会出现错误。

原因

int hi();

不矛盾

int hi(int);

因为一个没有任何参数的声明意味着你说你真的不知道有多少参数或它们是什么类型。这与第一份声明并不矛盾。因为你已经声明了,编译器将简单地使用该声明。hi


正如评论中所指出的,这将随着 C23 标准而改变。它采用了 C++ 的语义,即没有显式参数意味着 ,所以void

int hi();

将等同于

int hi(void);

这当然意味着这两个声明相互矛盾。

评论

4赞 Jonathan Leffler 5/3/2023
请注意,在 C23 中,两个函数声明将相互矛盾。声明将像 C++ 一样,等价于 ,这确实会与 相矛盾。在那之前,这种分析是合理的。int hi();int hi(void);int hi(int);
0赞 Some programmer dude 5/3/2023
@JonathanLeffler 啊,所以他们采用了C++语义?不知道。谢谢:)
5赞 Vlad from Moscow 5/3/2023 #2

如果其中没有多个函数定义,则可以使用多个兼容的函数声明。

在 C 语言中,定义了兼容类型的概念。

从 C11 标准(6.2.7 兼容型和复合型)

1 如果两种类型相同,则两种类型具有兼容类型。 用于确定两种类型是否兼容的其他规则包括 在 6.7.2 中对类型说明符进行了描述,在 6.7.3 中对类型限定符进行了描述, 以及 6.7.6 中的声明者。

(6.7 声明)

4 同一作用域中引用同一对象的所有声明,或 函数应指定兼容类型。

最后(6.7.6.3 函数声明器(包括原型))

  1. ...如果一种类型具有参数类型列表,而另一种类型具有参数类型列表 由不属于函数的函数声明符指定 定义,其中包含一个空标识符列表,即参数 列表不应有省略号终止符和每个终止符的类型 参数应与 应用默认参数升级。

在这两个函数声明中

int hi(int);
int hi();

返回类型是兼容的(它们是相同的)。第一个函数声明的参数具有与整数提升类型相对应的类型。int

来自 C11 标准 6.5.2.2 函数调用)

6 如果表示被调用函数的表达式的类型 不包括原型,则整数提升是在 每个参数和类型为 float 的参数将提升为 双。这些称为默认参数升级

例如,如果你会写

int hi(char);
int hi();

然后声明了两个不同的函数,因为类型,第一个函数的参数类型,与默认参数提升后的类型不对应。char

声明两个兼容函数和两个不同函数的另一个示例。

这两个声明声明相同的函数

int hi( double );
int hi();

这两个声明声明了不同的(不兼容的)函数

int hi( float );
int hi(); 

在 C23 标准中,相对于函数声明进行了以下更改

— 参数列表为空的强制函数声明 与仅包含单个空隙的参数列表相同;

所以根据 C23 标准,这些函数声明

int hi(int);
int hi();

相当于

int hi(int);
int hi( void );

因此,它们声明了两个不同的函数,编译器应该发出一条消息。