函数原型 - 关闭参数检查

问题描述:

来自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) { 
    ^

任何解释吗?

+5

gcc增加:'注意:具有默认提升的参数类型不能匹配空参数名称列表声明',所以'void test(double a)'工作,但'void test(float a)'doesn “T。因此,似乎“关闭了类型和参数检查并且没有任何关于争论的事情”是过于简单化了。您应该参考C规范以查看规则的实际内容。 – ikegami

+0

请参阅http://stackoverflow.com/questions/1630631/alternative-kr-c-syntax-for-function-declaration-versus-prototypes某些人可能会认为这个问题是该问题的重复,并关闭。 –

+1

编译器期望定义'void test(double a){}',因为'test(34.5f);'调用涉及_default参数promotions_,如果给定的声明不作为原型,就是这种情况。其中一种促销是“float ---> double”。 –

你告诉gcc编译c11代码,而不是为K & R.

我看着-std=选项,但没有人站出来为有用。也许完全省略语言标准参数会有所帮助。或者将其指定为c89

在c11中,总是需要完整形状的原型。所以第一次使用的功能是参数= (void)。在pre-C++中,这确实意味着“可能有或没有参数通过”。

+0

,它仍然是一个错误“在c11中,总是需要完整形状的原型。”Citation? – Ryan

+0

nope,用c89试过。没有使用这个编译。 – BalaK

+0

@Ryan:这不是c11的主要增强之一吗?或者,也许我正在考虑C++ 11? – wallyk

当函数声明不止一次时,所有声明必须有兼容类型(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类型。

+1

即使没有函数调用,代码仍然是违反约束的 –

因此,最后从这里给出的所有答案以及一点点阅读中,我学到了这些(我将它作为答案发布,以便将来任何人都可能会遇到这个问题) :

  • 当我打电话test(23.4f) - 参数自动“强制”为双和,因为没有指定原型将被称为test(double)(为自变量,至少)
  • 由于任何呼叫我让使用任何参数将被转换为'默认促销',我不能将函数声明为test(float),因为它永远不会被使用/调用编辑。因此,test(double)作品和test(float)不。

纠正我,如果我错了,我会编辑我的答案。

根据错误消息,具有默认升级的参数类型不能匹配空参数名称列表声明。所以问题是float将被提升为int,这会导致与函数定义的参数float不匹配。

声明:

void test(); 

它告诉了存在功能test这是任何参数,而不是返回一个值的编译器。

定义:

void test(float a) 

这是告诉编译器什么test()实际上也提供了申报为好。