Search code examples
cdefinitionfunction-declarationfunction-prototypes

Strange behavior of float in function definition. And declaration-definition mismatch, yet it works, how?


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.


Solution

  • 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 fs 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).