Correct format specifier for double in printf
Correct format specifier for double in printf
Question
What is the correct format specifier for double
in printf? Is it %f
or is it %lf
? I believe it's %f
, but I am not sure.
Code sample
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
Accepted Answer
"%f"
is the (or at least one) correct format for a double. There is no format for a float
, because if you attempt to pass a float
to printf
, it'll be promoted to double
before printf
receives it1. "%lf"
is also acceptable under the current standard -- the l
is specified as having no effect if followed by the f
conversion specifier (among others).
Note that this is one place that printf
format strings differ substantially from scanf
(and fscanf
, etc.) format strings. For output, you're passing a value, which will be promoted from float
to double
when passed as a variadic parameter. For input you're passing a pointer, which is not promoted, so you have to tell scanf
whether you want to read a float
or a double
, so for scanf
, %f
means you want to read a float
and %lf
means you want to read a double
(and, for what it's worth, for a long double
, you use %Lf
for either printf
or scanf
).
1. C99, §6.5.2.2/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." In C++ the wording is somewhat different (e.g., it doesn't use the word "prototype") but the effect is the same: all the variadic parameters undergo default promotions before they're received by the function.
Read more… Read less…
Given the C99 standard (namely, the N1256 draft), the rules depend on the function kind: fprintf (printf, sprintf, ...) or scanf.
Here are relevant parts extracted:
Foreword
This second edition cancels and replaces the first edition, ISO/IEC 9899:1990, as amended and corrected by ISO/IEC 9899/COR1:1994, ISO/IEC 9899/AMD1:1995, and ISO/IEC 9899/COR2:1996. Major changes from the previous edition include:
%lf
conversion specifier allowed inprintf
7.19.6.1 The
fprintf
function7 The length modifiers and their meanings are:
l (ell) Specifies that (...) has no effect on a following a, A, e, E, f, F, g, or G conversion specifier.
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to a long double argument.
The same rules specified for fprintf
apply for printf
, sprintf
and similar functions.
7.19.6.2 The
fscanf
function11 The length modifiers and their meanings are:
l (ell) Specifies that (...) that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to double;
L Specifies that a following a, A, e, E, f, F, g, or G conversion specifier applies to an argument with type pointer to long double.
12 The conversion specifiers and their meanings are: a,e,f,g Matches an optionally signed floating-point number, (...)
14 The conversion specifiers A, E, F, G, and X are also valid and behave the same as, respectively, a, e, f, g, and x.
The long story short, for fprintf
the following specifiers and corresponding types are specified:
%f
-> double%Lf
-> long double.
and for fscanf
it is:
%f
-> float%lf
-> double%Lf
-> long double.
Format %lf
is a perfectly correct printf
format for double
, exactly as you used it. There's nothing wrong with your code.
Format %lf
in printf
was not supported in old (pre-C99) versions of C language, which created superficial "inconsistency" between format specifiers for double
in printf
and scanf
. That superficial inconsistency has been fixed in C99.
You are not required to use %lf
with double
in printf
. You can use %f
as well, if you so prefer (%lf
and %f
are equivalent in printf
). But in modern C it makes perfect sense to prefer to use %f
with float
, %lf
with double
and %Lf
with long double
, consistently in both printf
and scanf
.
%Lf
(note the capital L
) is the format specifier for long doubles.
For plain doubles
, either %e
, %E
, %f
, %g
or %G
will do.