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:
- Why does the first example work even though there is a mismatch in the declaration and the definition?
- Why does it not work when the parameter-type is
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
declaration does not fully declare the function, i.e. it does not introduce the prototype. It only announces the fact that function
fexists and that its return type isdouble. It says absolutely nothing about the number and the types offs 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
voidin the parameter listThat 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 tofloat.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
doubleargument and the function is declared with adoubleparameter. So everything is matching. But when you call it with adoubleargument and declare it with afloatparameter, you get a mismatch.Also note, that when a function is declared without a prototype,
floatarguments are always promoted todoublearguments. For this reason, it is not possible to pass afloatargument to a function declared with()parameter list. If you want to havefloatarguments, always use prototypes (the same applies tocharandshortarguments as well).