How does the following code work even though the signature of the function in the declaration doesn't match with the definition? The function declaration has empty parameter list, yet the definition has one parameter. Why the compiler doesn't give error?
#include <stdio.h>
double f(); //function declaration
int main(void)
{
printf("%f\n", f(100.0));
}
double f(double param) //function definition
{
return 5 * param ;
}
It compiles and runs fine (ideone).
But if I change the type of the parameter in the definition, from double
to float
, it gives the following error (ideone):
prog.c:7: error: conflicting types for ‘f’
prog.c:8: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
prog.c:2: error: previous declaration of ‘f’ was here
What is wrong with float
? Why does it give error with float
but not with double
?
Here is the list of pairs of declaration and definition, along with which pair works, and which not:
Works (ideone)
double f(); //declaration
double f(double param); //definition
Does not work (ideone)
double f(); //declaration
double f(float param); //definition
Works (ideone)
float f(); //declaration
float f(double param); //definition
Does not work (ideone)
float f(); //declaration
float f(float param); //definition
So as it seems, whenever the parameter-type is float
, it doesn't work!
So I've basically two questions:
float
?I tried understanding the section §6.5.2.2 (C99), but the language is so cryptic that I couldn't clearly understand. I don't even know if I read the correct section. So please explain these behaviors in simple words.
Your assumption that declaration does not match the definition is incorrect. (That would be the case in C++, but not in C). In C language the
double f();
declaration does not fully declare the function, i.e. it does not introduce the prototype. It only announces the fact that function f
exists and that its return type is double
. It says absolutely nothing about the number and the types of f
s arguments. The arguments can be absolutely anything. In that sense the declaration in your example does match the definition (i.e. it doesn't contradict the definition, which is good enought for C compiler).
If you really wanted the declare a function that takes no arguments, you'd have to specify an explicit void
in the parameter list
double f(void);
That would indeed contradict the definition. What you have originally does not.
When you call a function that has been declared with empty parameter list ()
, it is your responsibility to supply the proper number of arguments of proper type. If you make a mistake, the behavior is undefined. This is what the compiler warns you about when you change the actual parameter type to float
.
Your analysis of "pairs" of declaration and definition is not entirely correct. It is misguided. It is not really about the declaration and definition. It is really about the definition and the way you call your function. In the original case you call it with a double
argument and the function is declared with a double
parameter. So everything is matching. But when you call it with a double
argument and declare it with a float
parameter, you get a mismatch.
Also note, that when a function is declared without a prototype, float
arguments are always promoted to double
arguments. For this reason, it is not possible to pass a float
argument to a function declared with ()
parameter list. If you want to have float
arguments, always use prototypes (the same applies to char
and short
arguments as well).