当函数没有参数时,为什么我没有收到 "conflicting types" 错误?

Why don't I get a "conflicting types" error when function has no arguments?

在此示例中,我收到了预期的 Conflicting types 错误:

#include <stdio.h>

int a(int b);

int a(int *b){
 return 6;
}

int main(){
 return 0;
}

但在这个例子中不是:

#include <stdio.h>

int a(int b);

int a(){
 return 6;
}

int main(){
 return 0;
}

为什么 a 的声明和定义仍然不同,但第二个示例编译正常?

概况和历史

由于C语言的发展历史,int a()并不意味着“a不带参数和returns一个int。”这意味着“a 接受未指定的参数和 returns 一个 int。”

由于“未指定的参数”在名义上与“一个 int 的参数”兼容,编译器不会为类型冲突给出错误。由于 C 中的进一步规则(参见下面的“函数兼容性”),类型不兼容,但编译器不需要对此进行诊断。

最初在 C 中,函数是用 () 的参数列表声明的,由调用者提供正确的类型。 (此外,参数被“提升”;char 参数被转换为 int,等等,但这是一个单独的问题。)在定义函数的地方,它是用参数名称定义的,例如 int a(b),然后是这些参数的声明,例如:

int a()
int b;
{
    return 6*b;
}

但这只是为了定义。声明没有那些参数类型的声明。

后来,为了完善函数的类型信息,C 语言添加了包括参数类型在内的函数完整声明的语法,例如int a(int b)。但是,由于旧语法已经使用 int a() 来表示“未指定的参数”,因此该语言必须保留该含义以支持旧代码。

相反,指定了一种特殊形式来表示“无参数”,即将 void 单独放入参数列表中。 int a(void) 表示“a 是一个不带参数并返回 int 的函数。”所以,如果你声明一个函数为int a(void);,然后用int a(int b) { … }定义它,编译器会给你一个错误信息。

功能兼容性

函数类型在 C 2018 6.7.6.3 15 中兼容的规则之一说:

… If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters,…

声明int a(int b);有一个参数类型列表,只有一个参数。

这个定义:

int a(){
 return 6;
}

有一个空的标识符列表,并且在 int a(){ 之间没有定义任何参数。所以他们不同意参数的数量。但是,编译器不需要诊断这种不兼容性。

因为在 C(但不是 C++)中,a() 声明了一个具有未指定数量参数的函数。请改用 a(void)

C function with no parameters behavior

第二个例子:

int a(){ a 是一个带有 未指定 个参数的函数。所以任何数字都可以,因此没有错误。

这是一个编译器缺陷。

根据 C 标准(6.7.6.3 函数声明符(包括原型))

  1. ...If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier

所以在这些声明中

int a(int b);

int a(){
 return 6;
}

函数的参数数量不同,编译器应发出消息,因为名称 a 用于声明两个不同的函数。

例如运行这段代码使用gcc 8.3你会得到以下错误

prog.c: In function ‘a’:
prog.c:5:1: error: number of arguments doesn’t match prototype
 int a(){
 ^~~
prog.c:3:5: error: prototype declaration
 int a(int b);
     ^