从关于C的K&R书中,我推测如果函数原型声明省略了参数(就像在int foo();中一样),类型和参数检查将被关闭,并且不会假设参数与C的旧版本兼容,因此它不会破坏遗留代码。
但是下面的代码抛出了一个原型不匹配的编译错误:
#include <stdio.h>
void test();
int main(void) {
test(34.5f);
}
void test(float a) {
printf("%f\n", a);
}错误:
C:\***.c:7:6: error: conflicting types for 'test'
void test(float a) {
^有什么解释吗?
发布于 2017-02-04 08:21:25
当一个函数被多次声明时,所有声明必须具有兼容的类型(C11 6.2.7/2)。在您的代码中,f被声明了两次--该定义也被视为一个声明。
兼容函数类型的定义见C11 6.7.6.3/15:
要使两个函数类型兼容,两个函数类型都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用上保持一致;相应的参数应具有兼容的类型。如果一种类型具有参数类型列表,而另一种类型是由不是函数定义一部分且包含空标识符列表的函数声明符指定的,则参数列表不应具有省略号终止符,并且每个参数的类型应与应用默认实参提升所产生的类型兼容。如果一种类型具有参数类型列表,而另一种类型由包含(可能为空)标识符列表的函数定义指定,则两者应在参数数量上达成一致。每个原型参数的类型应与将默认参数提升应用到相应标识符的类型所产生的类型兼容。(在确定类型兼容性和复合类型时,使用函数或数组类型声明的每个参数都被视为具有调整后的类型,使用限定类型声明的每个参数都被视为具有其声明类型的未限定版本。)
因此,void test()和void test(float)是不兼容的。换句话说,在看到void test();之后,任何原型都必须只使用默认参数提升未更改的类型。在这些促销活动下,float将更改为double。
我相信从第一个C标准开始就是这样。
发布于 2017-02-04 08:24:55
使用double类型的参数定义函数。
void test(double a) {
//...
}问题出在这个调用中
test(34.5f);使用默认的参数提升将参数转换为双精度类型。
发布于 2017-02-04 13:13:07
根据错误消息,具有默认提升的参数类型不能与空的参数名列表声明匹配。因此,问题是float将被提升为int,这将导致与函数定义的float参数不匹配。
声明:
void test();它告诉编译器存在一个函数test,它没有参数,也不返回值。
定义:
void test(float a)它告诉编译器test()到底是什么,还提供了声明。
https://stackoverflow.com/questions/42034962
复制相似问题