Why is it that scanf()
needs the l
in "%lf
" when reading a double
, when printf()
can use "%f
" regardless of whether its argument is a double
or a float
?
Example code:
double d;
scanf("%lf", &d);
printf("%f", d);
Why is it that scanf()
needs the l
in "%lf
" when reading a double
, when printf()
can use "%f
" regardless of whether its argument is a double
or a float
?
Example code:
double d;
scanf("%lf", &d);
printf("%f", d);
Because C will promote floats to doubles for functions that take variable arguments. Pointers aren't promoted to anything, so you should be using
%lf
,%lg
or%le
(or%la
in C99) to read in doubles.Using either a float or a double value in a C expression will result in a value that is a double anyway, so printf can't tell the difference. Whereas a pointer to a double has to be explicitly signalled to scanf as distinct from a pointer to float, because what the pointer points to is what matters.
scanf
needs to know the size of the data being pointed at by&d
to fill it properly, whereas variadic functions promote floats to doubles (not entirely sure why), soprintf
is always getting adouble
.Because otherwise scanf will think you are passing a pointer to a float which is a smaller size than a double, and it will return an incorrect value.
Since С99 the matching between format specifiers and floating-point argument types in C is consistent between
printf
andscanf
. It is%f
forfloat
%lf
fordouble
%Lf
forlong double
It just so happens that when arguments of type
float
are passed as variadic parameters, such arguments are implicitly converted to typedouble
. This is the reason why inprintf
format specifiers%f
and%lf
are equivalent and interchangeable. Inprintf
you can "cross-use"%lf
withfloat
or%f
withdouble
.But there's no reason to actually do it in practice. Don't use
%f
toprintf
arguments of typedouble
. It is a widespread habit born back in C89/90 times, but it is a bad habit. Use%lf
inprintf
fordouble
and keep%f
reserved forfloat
arguments.