610

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? } 
3
  • 22
    If you're stuck with a C89 library, "%lf" is undefined; in C99 and C11 libraries it is defined to be the same as "%f". Commented Apr 29, 2012 at 0:06
  • 2
    Your variant is as correct as it ever gets. %lf is the correct format specifier for double. But it became so in C99. Before that one had to use %f. Commented May 7, 2016 at 19:59
  • The full list of the specifiers is here: stackoverflow.com/questions/79601134/… Commented Jul 2 at 3:21

5 Answers 5

810

"%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.

Sign up to request clarification or add additional context in comments.

7 Comments

Note that g++ rejects %lf when compiling with -Wall -Werror -pedantic: error: ISO C++ does not support the ‘%lf’ gnu_printf format
@kynan: If so (at leas assuming a current version of g++), that's a bug in g++. For C89/90 and C++98/03, allowing l was an extension. The C99/11 and C++11 standards require the implementation to allow it.
Curiously, scanf does want doubles represented by %lf: it complains that it expected float * and found double * with just %f.
@JerryCoffin g++ still defaults to g++98 mode
@EricDand That's because scanf takes pointers to where to store what it reads, so needs to know how big the space being pointed-at is, whereas printf takes the values themselves, and "default argument promotions" mean both end up as doubles, so the l is essentially optional.
|
66

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 in printf

7.19.6.1 The fprintf function

7 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 function

11 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.

Comments

37

It can be %f, %g or %e depending on how you want the number to be formatted. See here for more details. The l modifier is required in scanf with double, but not in printf.

3 Comments

-1: l (lowercase) modifier is for integer types (cplusplus.com/reference/clibrary/cstdio/printf), and L is for floating point types. Additionally, the L modifier expects a long double, not a plain double.
user470379: So where is the contradiction with my answer? Haven't I said that l is not required in printf for double.
For printf, the length modifier l is ignored in the case of floating point types because float arguments are always promoted to double. Jerry Coffin's answer has more information.
20

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.

1 Comment

With scanf(), "%f", "%lf" match a float *, double *, not float, double as implied by the last line.
13

%Lf (note the capital L) is the format specifier for long doubles.

For plain doubles, either %e, %E, %f, %g or %G will do.

3 Comments

What's the difference between %g and %G ?
@yanpas, lowercase / uppercase for the exponent symbol, respectively.
sorry, %g and %G do output E symbol. Also they output INF and inf in different cases

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.