函数原型 - 关闭参数检查
来自K & R Book on C,我收集了如果函数原型声明省略参数(如在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) {
^
任何解释吗?
当函数声明不止一次时,所有声明必须有兼容类型(C11 6.2.7/2)。在你的代码f
被声明两次 - 定义也算作一个声明。
“兼容功能型” 的定义是在C11 6.7.6.3/15:
For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. 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. (In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)
因此void test()
和void test(float)
是不相容的。换句话说,看到void test();
后,任何原型只能使用默认参数促销不变的类型。在这些促销活动下,float
更改为double
。
我相信自从第一个C标准以来就一直如此。
使用double
类型的参数定义函数。
void test(double a) {
//...
}
的问题是在这个呼叫
test(34.5f);
有使用默认参数推广是将参数转换成double类型。
即使没有函数调用,代码仍然是违反约束的 –
因此,最后从这里给出的所有答案以及一点点阅读中,我学到了这些(我将它作为答案发布,以便将来任何人都可能会遇到这个问题) :
- 当我打电话
test(23.4f)
- 参数自动“强制”为双和,因为没有指定原型将被称为test(double)
(为自变量,至少) - 由于任何呼叫我让使用任何参数将被转换为'默认促销',我不能将函数声明为
test(float)
,因为它永远不会被使用/调用编辑。因此,test(double)
作品和test(float)
不。
纠正我,如果我错了,我会编辑我的答案。
根据错误消息,具有默认升级的参数类型不能匹配空参数名称列表声明。所以问题是float
将被提升为int
,这会导致与函数定义的参数float
不匹配。
声明:
void test();
它告诉了存在功能test
这是任何参数,而不是返回一个值的编译器。
定义:
void test(float a)
这是告诉编译器什么test()
实际上也提供了申报为好。
gcc增加:'注意:具有默认提升的参数类型不能匹配空参数名称列表声明',所以'void test(double a)'工作,但'void test(float a)'doesn “T。因此,似乎“关闭了类型和参数检查并且没有任何关于争论的事情”是过于简单化了。您应该参考C规范以查看规则的实际内容。 – ikegami
请参阅http://stackoverflow.com/questions/1630631/alternative-kr-c-syntax-for-function-declaration-versus-prototypes某些人可能会认为这个问题是该问题的重复,并关闭。 –
编译器期望定义'void test(double a){}',因为'test(34.5f);'调用涉及_default参数promotions_,如果给定的声明不作为原型,就是这种情况。其中一种促销是“float ---> double”。 –