The short answer is that it has no impact on printf, and denotes use of float or double in scanf.
For printf, arguments of type float are promoted to double so both %f and %lf are used for double. For scanf, you should use %f for float and %lf for double.
More detail for the language lawyers among us below:
There is no difference between %f and %lf in the printf family. The ISO C standard (all references within are from C11), section 7.21.6.1 The fprintf function, paragraph /7 states, for the l modifier (my emphasis):
Specifies that a following
d,i,o,u,x, orXconversion specifier applies to along intorunsigned long intargument; that a followingnconversion specifier applies to a pointer to along intargument; that a followingcconversion specifier applies to awint_targument; that a followingsconversion specifier applies to a pointer to awchar_targument; or has no effect on a followinga,A,e,E,f,F,g, orGconversion specifier.
The reason it doesn’t need to modify the f specifier is because that specifier already denotes a double, from paragraph /8 of that same section where it lists the type for the %f specifier:
A
doubleargument representing a floating-point number is converted to decimal notation
That has to do with the fact that arguments following the ellipse in the function prototype are subject to default argument promotions as per section 6.5.2.2 Function calls, paragraph /7:
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.
Since printf (and the entire family of printf-like functions) is declared as int printf(const char * restrict format, ...); with the ellipsis notation, that rule applies here. The default argument promotions are covered in section 6.5.2.2 Function calls, paragraph /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
floatare promoted todouble. These are called the default argument promotions.
For the scanf family, it mandates the use of a double rather than a float. Section 7.21.6.2 The fscanf function /11:
Specifies that a following
d,i,o,u,x,X, ornconversion specifier applies to an argument with type pointer tolong intorunsigned long int; that a followinga,A,e,E,f,F,g, orGconversion specifier applies to an argument with type pointer todouble; or that a followingc,s, or[conversion specifier applies to an argument with type pointer towchar_t.
This modifies the /12 paragraph of that section that states, for %f:
Matches an optionally signed floating-point number, infinity, or
NaN, whose format is the same as expected for the subject sequence of thestrto