2

im having trouble understanding why this occurs: with the following code;

    #include <stdio.h>

    int main() 
    {
        double x=123;

        printf("x is %f. Enter a new value for x.\n", x);
        scanf("%f", &x);
        printf("x is %f\n", x);

        return 0;
    }

when you enter 45678 as the new value for x, 'x is 123.000017' is printed. I know that this is fixed when you use %lf when scanning, but why does this happen when using %f?

2 Answers2

3

I know that this is fixed when you use %lf when scanning, but why does this happen when using %f?

The difference between printf and scanf function arguments is that you pass values to printf, but to scanf you pass pointers (i.e. addresses of values). According to C rules, when a function takes a variable number of arguments, all parameters undergo default promotions.

One of the promotions is that floats get converted to double, in the same way that shorts get converted to int. That is why you can use %f or %lf with printf: both types of values are converted by the compiler to double, so accessing them is safe.

However, there is no such rule for pointers (and for a good reason: trying to write a double into a space of float would be undefined behavior). That is why you must differentiate between %f and %lf when passing parameters to the scanf family of functions.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1
 scanf("%f", &x);

should be

 scanf("%lf", &x);

There is a false symmetry for floating points conversion specifiers between printf and scanf.

Also note that lf conversion specifier is equivalent to f conversion specifier in printf (since c99, it was undefined before).

I know that this is fixed when you use %lf when scanning, but why does this happen when using %f?

f conversion specifier in scanf requires an argument of type pointer to float. By passing an argument of type pointer to double you invoke undefined behavior.

ouah
  • 142,963
  • 15
  • 272
  • 331