Q: Someone told me it was wrong to use %lf with printf. How can printf use %f for type double, if scanf requires %lf?
A: It's true that printf's %f specifier works with both float and double arguments.[footnote] Due to the ``default argument promotions'' (which apply in variable-length argument lists [footnote] such as printf's, whether or not prototypes are in scope), values of type float are promoted to double, and printf therefore sees only doubles. (printf does accept %Lf, for long double.) See also question 15.2.
scanf, on the other hand, accepts pointers, and no such promotions apply. Storing into a float (via a pointer) is very different from storing into a double, so scanf distinguishes between %f and %lf.
Here is a table listing the argument types expected by printf and scanf for the various format specifiers:
[TABLE GOES HERE]
(Strictly speaking, %lf is undefined under printf, though many systems probably accept it. To be portable, always use %f.)
See also question 12.13.
K&R1 Sec. 7.3 pp. 145-47, Sec. 7.4 pp. 147-50
K&R2 Sec. 7.2 pp. 153-44, Sec. 7.4 pp. 157-59
ISO Sec. 220.127.116.11, Sec. 18.104.22.168
H&S Sec. 15.8 pp. 357-64, Sec. 15.11 pp. 366-78
CT&P Sec. A.1 pp. 121-33