Why, in C, does printf() use %f for float and double but scanf() differentiates the use of both with %f and %lf?

Question:

When you want to print a value of type float or double using the printf() function, you use the %f specifier for both data types. For example:

double d = 3.5;
float f = 4.5;
printf("Valores: %f %f", f, d);

Whereas in the case of the scanf() , the %f specifier is used to read a float and the %lf specifier is used to read a double :

double d;
float f;
printf("Introduce un float y un double: ");
scanf("%f %lf", &f, &d);

Why are there different specifiers for float and double types in scanf() , but the same specifier in printf() ?

Answer:

The C language performs an implicit conversion from float to double when a float type value is passed as an argument to a function with a variable number of arguments , as in the case of the printf() function. Therefore, whether passing a float value or passing a double , the printf() function receives a double value, the %f specifier being set to print double values ​​in printf()

In the case of scanf() , values ​​( float or double type) are not passed as arguments, but rather pointers are passed with the memory addresses where to store the read values. Pointers are not implicitly converted by C, in addition to the fact that the scanf() must know what type of data is each of the variables where each read value is going to be stored, so as not to occupy larger memory areas than those reserved or not to save incorrectly formatted data to the corresponding variable. Therefore, a specific specifier is necessary for each variable with its corresponding data type.

Since the C99 standard, a specific specifier is established for each floating point data type, both for printf() and scanf() :

  • %f for float
  • %lf for double
  • %Lf for long double

By using the printf() function with the %f specifier, you can still safely use arguments of type float or double . Furthermore, it makes no difference to use %f or %lf with values ​​of type float or double . In all possible combinations between them, printf() implicitly converts to double and prints it as such. But using the specifier %lf with float values ​​or %f with double values ​​is considered bad practice and should be avoided, even if it doesn't initially cause problems.


To write this solution, much of the information from the English SO entry has been used: https://stackoverflow.com/questions/210590/why-does-scanf-need-lf-for-doubles-when-printf -is-okay-with-just-f

Scroll to Top