为什么具有空参数列表的函数原型与具有char参数的函数原型冲突?

时间:2014-02-18 15:40:30

标签: c gcc clang standards c11

使用下面的代码,使用-std = c11调用的clang和gcc都会抱怨foo的冲突类型。

int foo();

int main(void) {
  return foo(0);
}

int foo(char a) {
   return a;
}

根据https://stackoverflow.com/a/13950800/1078224中的答案,在(较旧的?)C标准中,当没有给出变量类型时,假设类型为int。但是,C11标准草案(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf),第6.7.6.3节,14美元表示

  

函数声明符中不属于a的空列表   该函数的定义指定没有关于数量或类型的信息   提供参数。

由此我得出结论,上面的代码实际上应该是有效的。或者我错过了标准的其他相关部分?

1 个答案:

答案 0 :(得分:11)

C 2011(N1570)6.7.6.3 15:

  

要兼容两种功能类型,两者都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数的数量和省略号终止符的使用中一致;相应的参数应具有兼容的类型。如果一个类型具有参数类型列表而另一个类型由函数声明符指定,该函数声明符不是函数定义的一部分且包含空标识符列表,则参数列表不应具有省略号终止符且类型为每个参数应与应用默认参数促销产生的类型兼容。... [强调添加。]

char被提升为int,因此char a与空列表不兼容。 int a会是;允许int foo(); int foo(int a);

基本上,原因是,如果你声明一个函数int foo()然后调用它,比如说int foo(3),编译器必须知道传递它的内容。从历史派生的规则是执行默认参数提升。因此,int foo(3)会被调用,就好像它是int foo(int)

然后,如果您稍后使用int foo(char)定义函数,则定义将与调用不匹配。在许多C实现中,charint可以放在相同的位置来调用函数,但是C实现可以做一些不同的事情。 floatdouble会产生更大的冲突。