在ANSI C前语法中混淆函数调用

时间:2011-09-29 18:50:39

标签: c function syntax

我正在处理一些pre-ANSI C语法。请参阅我在一个条件

中进行以下函数调用
 BPNN *net;
 // Some more code
 double val;
 // Some more code, and then,
 if (evaluate_performance(net, &val, 0)) {

但是函数evaluate_performance定义如下(下面具有上述条件的函数):

evaluate_performance(net, err)
BPNN *net;
double *err;
{

为什么evaluate_performance定义了两个参数但是用三个参数调用? '0'是什么意思?

顺便说一下,我很确定它并没有调用别处定义的其他evaluate_performance;我grep编辑了所有涉及的文件,我很确定我们应该在这里谈论相同的evaluate_performance

谢谢!

4 个答案:

答案 0 :(得分:7)

如果你调用一个没有声明原型的函数(就像这里的情况那样),那么编译器会假定它接受任意数量和类型的参数并返回int。此外,charshort参数会提升为intfloat会提升为double s(这些被称为默认参数)促销)。

这在新C代码中被认为是不好的做法,原因很明显 - 如果函数没有返回int,那么糟糕可以确保,你阻止编译器检查你传递了正确的数字和参数类型和参数可能会被错误地提升。

最新版本的C标准C99从语言中删除了这一功能,但实际上,许多编译器在C99模式下仍然允许使用它们,以保持传统兼容性。

对于额外参数,根据C89标准,它们在技术上是未定义的行为。但实际上,它们通常只会被运行时忽略。

答案 1 :(得分:3)

代码不正确,但不需要编译器进行诊断。 (C99编译器会抱怨它。)

旧式函数定义未指定函数所需的参数个数。对没有可见原型的函数的调用假定返回int并且具有调用隐含的参数的数量和类型(将窄整数类型提升为int或{{ 1}},unsigned int被提升为float)。 (C99删除了这个;根据C99标准,您的代码无效。)

即使定义在调用之前(旧式定义不提供原型),这也适用。

如果错误地调用了这样的函数,则行为未定义。换句话说,程序员有责任正确地提出论点;编译器不会诊断错误。

这显然不是一个理想的情况;它可能会导致很多未检测到的错误。

这正是ANSI为该语言添加原型的原因。

为什么还在处理旧式函数定义?你能更新代码以使用原型吗?

答案 2 :(得分:2)

即使是标准的C编译器在这方面也有些宽容。尝试运行以下内容:

int foo()
{
   printf("here");
}

int main()
{
   foo(3,4);
   return 0;
}

令人惊讶的是,输出"here"。额外的参数只是被忽略了。当然,这取决于编译器。

答案 3 :(得分:1)

C中不存在重载,因此有2个声明在同一文本中不起作用。

那个必须是一个相当古老的编译器才能在这个问题上犯错,或者它还没有找到函数的声明!

某些编译器在调用未定义函数时不会发出警告/错误。这可能就是你遇到的。我建议你看看编译器的命令行标志,看看是否有一个标志可以用来获取这些警告,因为你实际上可能会发现很多类似的错误(太多参数可能工作得很好,但也是如此很少有人会使用“未定义”值...)

请注意,在printf()中使用省略号时可以这样做(添加额外的参数):

printf(const char *format, ...);

我认为该函数在某个时刻有3个参数,最后一个被删除,因为它未被使用,而且代码的某些部分没有得到纠正。我会删除第3个参数,以防堆栈进入错误的顺序,因此无法将正确的参数发送到函数。