为什么声明带参数和不带参数的同一个函数不会导致编译错误?

ary*_*rye 6 c compiler-warnings integer-promotion function-declaration

对于代码:

int hi(int);
int hi();
int main()
{
    hi(3);
}
Run Code Online (Sandbox Code Playgroud)

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

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

Som*_*ude 7

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

原因是

int hi();
Run Code Online (Sandbox Code Playgroud)

并不矛盾

int hi(int);
Run Code Online (Sandbox Code Playgroud)

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


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

int hi();
Run Code Online (Sandbox Code Playgroud)

将相当于

int hi(void);
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,在 C23 中,两个函数声明将相互矛盾。`int hi();` 声明将像 C++ 一样,等同于 `int hi(void);`,这确实与 `int hi(int);` 相矛盾。在那之前,这个分析是合理的。 (4认同)

Vla*_*cow 5

如果其中不超过一个函数定义,则可以使用多个兼容的函数声明。

\n

C 中定义了兼容类型的概念。

\n

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

\n
\n

1 如果两个类型的类型相同,则它们具有兼容类型。\n用于确定两个类型是否兼容的其他规则\n在类型说明符的 6.7.2 中、类型限定符的 6.7.3 中和声明符的 6.7.6 中描述。 。

\n
\n

和(6.7 声明)

\n
\n

4 同一范围内引用同一对象或函数的所有声明应指定兼容类型。

\n
\n

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

\n
\n
    \n
  1. ...如果一种类型具有参数类型列表,而另一种类型由不属于函数定义的一部分且包含空标识符列表的函数声明符指定,则参数列表不应具有省略号终止符,并且每个参数的类型应与应用默认参数提升所产生的类型兼容。
  2. \n
\n
\n

在这两个函数声明中

\n
int hi(int);\nint hi();\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

来自 C11 标准 6.5.2.2 函数调用)

\n
\n

6 如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并将 float 类型的参数提升为 double。这些称为默认参数促销

\n
\n

例如,如果你写

\n
int hi(char);\nint hi();\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

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

\n

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

\n
int hi( double );\nint hi();\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
int hi( float );\nint hi(); \n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
\n

\xe2\x80\x94 参数列表为空的强制函数声明将被视为与仅包含单个 void 的参数列表相同;

\n
\n

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

\n
int hi(int);\nint hi();\n
Run Code Online (Sandbox Code Playgroud)\n

相当于

\n
int hi(int);\nint hi( void );\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n