As answered by @Chris McGrath, you must use the %lf
format specifier for doubles. However, this doesn't explain why the %f
format works just fine for printf
.
%lf
stands for long float
, i.e. double
. When values of type float
are passed to variadic functions (those accepting a variable number of arguments, such as printf
and scanf
), they are implicitly promoted to double
:
float val;
printf("%f", val); /* printf receives val cast to double, the same
as printf("%f", (double) val) */
printf("%lf", val); /* printf also receives val cast to double, the
same as printf("%lf", (double) val) */
Since both printf("%lf", ...)
and printf("%f", ...)
end up receiving a double
, the two are completely equivalent.
On the other hand, all arguments to scanf
are pointers. scanf("%f", ...)
expects to receive a float *
, and scanf("%lf", ...)
a double *
:
float floatval;
double dblval;
scanf("%f", &floatval); /* stores a float value to address received */
scanf("%lf", &dblval); /* stores a double value to address received */
The two pointers point to different types, so one cannot be promoted to the other. If they received the same treatment by scanf
, it would end up storing the same value into addresses allocated for types of different size, which cannot work.
This is why scanf
strictly requires the use of the %lf
specifier when used with double
values.