The C standard library implementation you're using doesn't conform to C99 (or newer). The changes listed in the foreword (paragraph 5) contain:
%lf
conversion specifier allowed in printf
The description of the l
length modifier is (C99+TC3 7.19.6.1 par. 7, emphasis mine):
Specifies that a following d
, i
, o
, u
, x
, or X
conversion specifier applies to a long int
or unsigned long int
argument; that a following n
conversion specifier applies to a pointer to a long int argument
; that a following c
conversion specifier applies to a wint_t
argument; that a following s
conversion specifier applies to a pointer to a wchar_t
argument; or has no effect on a following a
, A
, e
, E
, f
, F
, g
, or G
conversion specifier.
%f
and %lf
are therefore equivalent. Both expect a double
because arguments matching the ellipsis (the ...
in int printf(char const * restrict, ...);
) undergo the so-called default argument promotions. Among other things they implicitly convert float
to double
. It doesn't matter for scanf()
since pointers aren't implicitly converted.
So if you can't or don't want to update to a newer C standard library %f
can always be used in a printf()
format string to print float
or double
. However in scanf()
format strings %f
expects float*
and %lf
expects double*
.