From the C Standard (7.21.6.1 The fprintf function)
l (ell) 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.
and (6.5.2.2 Function calls)
7 If the expression that denotes the called function has a type that
does include a prototype, the arguments are implicitly converted, as
if by assignment, to the types of the corresponding parameters, taking
the type of each parameter to be the unqualified version of its
declared type. The ellipsis notation in a function prototype
declarator causes argument type conversion to stop after the last
declared parameter. The default argument promotions are performed on
trailing arguments.
and
6 If the expression that denotes the called function has a type that
does not include a prototype, the integer promotions are performed on
each argument, and arguments that have type float are promoted to
double. These are called the default argument promotions.
Using the length modifier l
with the conversion specifier f
will only confuse readers of the code. Its using will arise questions. The readers of the code will think that either the author of the code does not know that the length modifier has no effect or that without the length modifier a call of printf
(or fprintf
) will indeed have undefined behavior and using the length modifier is necessary.
As for using the length modifier with a call of scanf
then the function deals with pointers of the type float *
or double *
. That is the default argument promotions are not applied to them. So to distinguish whether a pointer points to an object of the type float
or to an object of the type double
you have to use the length modifier l
with the conversion specifier f
with pointers of the type double *
or without the length modifier with pointers of the type float *
.
Adepts of using the length modifier l
with objects of the type double
in calls of printf
(or fprintf
) only make code less maintainable because for example if the type of an outputted variable will be changed from the type double
to the type float
they will have to find and change all calls printf where the variable is used.