skytreader
skytreader

Reputation: 11707

Confused over function call in pre-ANSI C syntax

I'm dealing with some pre-ANSI C syntax. See I have the following function call in one conditional

 BPNN *net;
 // Some more code
 double val;
 // Some more code, and then,
 if (evaluate_performance(net, &val, 0)) {

But then the function evaluate_performance was defined as follows (below the function which has the above-mentioned conditional):

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

How come evaluate_performance was defined with two parameters but called with three arguments? What does the '0' mean?

And, by the way, I'm pretty sure that it isn't calling some other evaluate_performance defined elsewhere; I've greped through all the files involved and I'm pretty sure the we are supposed to be talking about the same evaluate_performance here.

Thanks!

Upvotes: 6

Views: 2434

Answers (4)

Keith Thompson
Keith Thompson

Reputation: 263557

The code is incorrect, but in a way that a compiler is not required to diagnose. (A C99 compiler would complain about it.)

Old-style function definitions don't specify the number of arguments a function expects. A call to a function without a visible prototype is assumed to return int and to have the number and type(s) of arguments implied by the calls (with narrow integer types being promoted to int or unsigned int, and float being promoted to double). (C99 removed this; your code is invalid under the C99 standard.)

This applies even if the definition precedes the call (an old-style definition doesn't provide a prototype).

If such a function is called incorrectly, the behavior is undefined. In other words, it's entirely the programmer's responsibility to get the arguments right; the compiler won't diagnose errors.

This obviously isn't an ideal situation; it can lead to lots of undetected errors.

Which is exactly why ANSI added prototypes to the language.

Why are you still dealing with old-style function definitions? Can you update the code to use prototypes?

Upvotes: 3

Alexis Wilke
Alexis Wilke

Reputation: 20798

Overloading doesn't exist in C so having 2 declarations would not work in the same text.

That must be a quite old compiler to not err on this one or it did not find the declaration of the function yet!

Some compilers would not warn/err when calling an undefined function. That's probably what you're running into. I would suggest you look at the command line flags of the compiler to see whether there is a flag you can use to get these warnings because you may actually find quite a few similar mistakes (too many parameters is likely to work just fine, but too few will make use of "undefined" values...)

Note that it is possible to do such (add extra parameters) when using the ellipsis as in printf():

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

I would imagine that the function had 3 parameters at some point and the last was removed because it was unused and some parts of the code was not corrected as it ought to be. I would remove that 3rd parameter, just in case the stack goes in the wrong order and thus fails to send the correct parameters to the function.

Upvotes: 2

Adam Rosenfield
Adam Rosenfield

Reputation: 400522

If you call a function that doesn't have a declared prototype (as is the case here), then the compiler assumes that it takes an arbitrary number and types of arguments and returns an int. Furthermore, char and short arguments are promoted to ints, and floats are promoted to doubles (these are called the default argument promotions).

This is considered bad practice in new C code, for obvious reasons -- if the function doesn't return int, badness could ensure, you prevent the compiler from checking that you're passing the correct number and types of parameters, and arguments might get promoted incorrectly.

C99, the latest edition of the C standard, removes this feature from the language, but in practice many compilers still allow them even when operating in C99 mode, for legacy compatibility.

As for the extra parameters, they are technically undefined behavior according to the C89 standard. But in practice, they will typically just be ignored by the runtime.

Upvotes: 8

Luchian Grigore
Luchian Grigore

Reputation: 258628

Even standard C compilers are somewhat permissive when it comes to this. Try running the following:

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

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

It will, to some's surprise, output "here". The extra arguments are just ignored. Of course, it depends on the compiler.

Upvotes: 3

Related Questions