Samuelliyi
Samuelliyi

Reputation: 68

Weird results due to argument promotion when missing the prototype declaration in C

I have encounter a problem which can be summarized as follows,

#include <stdio.h>
int main()
{
        float f=23.45;
        printf("main: %f\n", f);
        t1(f);
/*    the result would be 
      main:23.450001 
      t1:2.000000    */          
}
void t1(float f)
{
        printf("t1: %f\n", f);
}

I know now that the weird behavior is due to missing of prototype declaration and the arguments are thus promoted,(float->double?),still i cannot figure out why the result is 2.000000,so can anyone give a more detailed explanation? I am using ubuntu10.04 gcc4.4.3

Upvotes: 0

Views: 136

Answers (3)

Pascal Cuoq
Pascal Cuoq

Reputation: 80276

The behavior you are observing is specific to stack-based parameter passing. For people who compile 64-bit x86 code by default and are unable to reproduce it, you can try with "gcc -m32" instead of just "gcc".

With stack-based parameter passing, t1() read 32 bits from the stack, and these 32 bits happen to form the floating-point value 2.0. At the call site, because t1 did not have a prototype, the argument f was promoted to double and it was a double that was written on the stack (C99 6.5.2.2:6 “If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions”).

There is no reason for t1 to recover the intended value from the stack since it does not read it properly with the same type and width it was written.

Upvotes: 6

David Schwartz
David Schwartz

Reputation: 182763

Because the compiler does not know that t1 takes a float, it promotes the float to a double. On your platform, t1 interprets the first four bytes of that double as a float.

2.0 is represented as 1 x 2^0, which in binary is three zero bytes followed by a 64 (on x86-64). As it happens, 23.45 as a double has the same first four bytes, 0, 0, 0, 64 (followed by 51, 115, 55, 64). So if you take the double 23.45 and interpret the first four bytes of it as a float, you get 2.0.

Upvotes: 1

thiton
thiton

Reputation: 36049

Remember that a missing prototype implies the function will later be declared with int arguments, and that appropriate conversions take place. So, I assume if you replace the float by int in the declaration of t1, you'll get a result of 23.

Upvotes: 0

Related Questions