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.
Since С99 the matching between format specifiers and floating-point argument types in C is consistent between printf
and scanf
. It is
%f
for float
%lf
for double
%Lf
for long double
It just so happens that when arguments of type float
are passed as variadic parameters, such arguments are implicitly converted to type double
. This is the reason why in printf
format specifiers %f
and %lf
are equivalent and interchangeable. In printf
you can "cross-use" %lf
with float
or %f
with double
.
But there's no reason to actually do it in practice. Don't use %f
to printf
arguments of type double
. It is a widespread habit born back in C89/90 times, but it is a bad habit. Use %lf
in printf
for double
and keep %f
reserved for float
arguments.
%f
in printf is a good habit because then your code always works, whereas using %lf
may fail if the compiler does not have a C99 compliant library. Unfortunately that situation does happen in reality. –
Dissidence printf
and scanf
. Note that this does not imply that using the same format specifier means that the data written by a [f]printf()
can be read by [f]scanf()
. In general, using the same format specifier for scanf()
that was used by printf()
will not successfully read the data. For example, space padding that can be inserted by a prinf()
's "%d"
format specifier will be skipped by that same "%d"
format specifier in a scanf()
call. –
Scurrility 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), so printf
is always getting a double
.
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.
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.
float
values were automatically promoted to double
in expressions. That rule was abandoned in standard C. Generally, float
does not get promoted to double
in expressions. It only gets promoted to double
when passed as a variadic argument, which is what happens in this case. –
Noumenon © 2022 - 2024 — McMap. All rights reserved.
&
operator, the result of that operation is a pointer to the variable's storage location in memory. It is that pointer which is passed toscanf
. – Fane