Question

Correct Format Specifier for double in printf in C

cfloating-pointprintfdoubleformat-specifiers

Question

In C, what is the correct format specifier for printing a double value with printf? Should it be %f or %lf?

I think %f is correct, but I am not completely sure.

#include <stdio.h>

int main(void)
{
    double d = 1.4;
    printf("%lf", d); // Is this wrong?
    return 0;
}

Short Answer

By the end of this page, you will understand how printf handles double values in C, when %f and %lf are valid, and why printf and scanf behave differently for floating-point types. You will also see common mistakes, practical examples, and a small project to reinforce the idea.

Concept

In C, the correct and standard format specifier for printing a double with printf is %f.

For printf-style functions:

  • %f prints a floating-point value
  • double arguments are expected for %f
  • %lf in printf is typically treated the same as %f by modern compilers and libraries, but the important thing to learn is that %f is the normal specifier for double in printf

Why this happens

The reason is based on default argument promotions in variadic functions like printf.

When you pass arguments to printf, there is no fixed parameter type information for the extra arguments, so C applies promotions:

  • float becomes double
  • smaller integer types such as char and short become int

That means printf never directly receives a float argument. If you write:

float x = 3.5f;
printf("%f", x);

x is automatically promoted to double before printf receives it.

So for output:

  • float -> promoted to double
  • double -> stays double
  • both are printed with %f

Why this matters

This is important because format specifiers must match the actual argument types expected by functions like printf and scanf.

If you use the wrong specifier:

  • output may be incorrect
  • input may fail
  • you may trigger undefined behavior in some cases
  • compilers may warn you

A very common source of confusion is that scanf is different:

  • printf("%f", someDouble) uses %f
  • scanf("%lf", &someDouble) uses %lf

So the key lesson is:

  • printf: use %f for double
  • scanf: use %lf for double

Mental Model

Think of printf as a display clerk who receives all decimal numbers in one standard delivery box: double.

Even if you send a float, it gets repackaged into a double before arriving. So the clerk expects the %f label when printing normal floating-point values.

Now think of scanf as a storage clerk who must place the value into the correct size box in memory:

  • %f means “store into a float*”
  • %lf means “store into a double*”

So:

  • printf cares about the promoted value type it receives
  • scanf cares about the exact pointer type where it will write the value
Take Quiz

Syntax and Examples

Core syntax

printf("%f", value);

For a double:

double d = 1.4;
printf("%f", d);

Example: printing a double

#include <stdio.h>

int main(void)
{
    double d = 1.4;
    printf("%f\n", d);
    return 0;
}

Output:

1.400000

By default, %f prints 6 digits after the decimal point.

Example: controlling precision

#include <stdio.h>

int main(void)
{
    double pi = 3.1415926535;

    printf("Default: %f\n", pi);
    printf("2 decimal places: %.2f\n", pi);
    printf("4 decimal places: %.4f\n", pi);

    return 0;
}

Output:

Default: 3.141593
2 decimal places: 3.14
4 decimal places: 3.1416

Example: float also uses %f in printf

#include <stdio.h>

int main(void)
{
    float f = 2.5f;
    double d = 2.5;

    printf("float: %f\n", f);
    printf("double: %f\n", d);

    return 0;
}

Both lines are valid because float is promoted to double when passed to printf.

About %lf in printf

You may see code like this:

printf("%lf\n", d);

In printf, this works the same as %f in common C implementations. But for clarity and correctness in learning, prefer %f when printing a double. The real distinction between %f and %lf matters much more in scanf.

Step by Step Execution

Consider this example:

#include <stdio.h>

int main(void)
{
    double d = 1.4;
    printf("Value = %.2f\n", d);
    return 0;
}

Step-by-step

1. A double variable is created

double d = 1.4;
  • d stores a floating-point number
  • its type is double

2. printf is called

printf("Value = %.2f\n", d);

The format string contains:

  • Value = -> printed as plain text
  • %.2f -> print a floating-point value with 2 digits after the decimal point
  • \n -> print a newline

3. printf reads the format specifier

It sees %.2f, so it expects a floating-point argument of type double.

4. The argument matches

d is already a double, so it matches what printf expects.

5. Output is produced

Value = 1.40

What if the variable were float?

float f = 1.4f;
printf("%.2f\n", f);

This still works because f is promoted to double before printf receives it.

Real World Use Cases

Floating-point output appears in many real programs.

Common examples

  • Finance tools: printing totals, tax, interest, or exchange rates
  • Sensor applications: showing temperature, pressure, or voltage readings
  • Scientific programs: printing measurements and computed results
  • Game development: displaying coordinates, speed, or frame timing
  • APIs and logs: recording decimal values for debugging or monitoring

Example: temperature logger

#include <stdio.h>

int main(void)
{
    double temperature = 23.6789;
    printf("Temperature: %.1f C\n", temperature);
    return 0;
}

Example: price display

#include <stdio.h>

int main(void)
{
    double price = 19.99;
    printf("Price: $%.2f\n", price);
    return 0;
}

In these cases, choosing the right precision is often as important as choosing the right format specifier.

Take Quiz

Real Codebase Usage

In real codebases, developers rarely use printf with just bare %f everywhere. They usually combine it with formatting decisions, validation, and readability patterns.

Common patterns

Fixed precision for user-facing output

printf("Average response time: %.2f ms\n", avg);

This avoids noisy output like many unnecessary decimal places.

Debug logging

printf("x=%f, y=%f, z=%f\n", x, y, z);

Useful in small tools or command-line programs.

Guarding calculations before printing

if (count == 0)
{
    printf("No data available.\n");
    return 0;
}

printf("Average: %.2f\n", total / count);

This is a simple guard clause pattern: check invalid conditions early.

Input/output pairing

Developers often read a double with scanf("%lf", &value) and later print it with printf("%f", value).

#include <stdio.h>

int main(void)
{
    double value;

    if (scanf("%lf", &value) != 1)
    {
        printf("Invalid input.\n");
        return 1;
    }

    printf("You entered: %.3f\n", value);
    return 0;
}

This pattern is very common in console programs.

Common Mistakes

1. Mixing up printf and scanf

This is the most common mistake.

Wrong idea

  • %lf must always be used for double

That is not the rule.

Correct rule

  • printf uses %f for double
  • scanf uses %lf for double

2. Using %d for a floating-point value

Broken code:

double d = 1.4;
printf("%d\n", d);

Why it is wrong:

  • %d is for int
  • d is a double
  • the format and argument type do not match

Use this instead:

printf("%f\n", d);

3. Expecting %f to show only the necessary decimal places

double d = 1.4;
printf("%f\n", d);

Output:

1.400000

Beginners often expect 1.4, but %f shows 6 digits after the decimal by default.

Use precision when needed:

printf("%.1f\n", d);

4. Forgetting that float is promoted in printf

Some learners think float needs a different specifier in printf.

float f = 2.5f;
printf("%f\n", f);

This is correct because float is promoted to double.

5. Using the wrong specifier in scanf

Broken code:

double d;
scanf("%f", &d);

Why it is wrong:

  • %f in scanf expects float *
  • &d is double *

Correct version:

double d;
scanf("%lf", &d);

6. Ignoring compiler warnings

If your compiler warns about format mismatches, do not ignore it. These warnings often catch real bugs.

Compile with warnings enabled when possible:

gcc -Wall -Wextra -pedantic program.c

Comparisons

printf vs scanf for floating-point values

FunctionfloatdoubleWhy
printf%f%ffloat is promoted to double
scanf%f%lfscanf needs the exact pointer type

%f vs %lf in printf

SpecifierMeaning in printfPractical advice
%fPrint a floating-point value (double)Use this for double output
%lfTreated the same as %f in printfUsually works, but %f is clearer

Related floating-point output specifiers

SpecifierExample outputUse case
%f3.140000Fixed-point decimal output
%e3.140000e+00Scientific notation
%g3.14Shorter, more compact output

Example comparison

#include <stdio.h>

int main(void)
{
    double x = 1234.5678;

    printf("%%f: %f\n", x);
    printf("%%e: %e\n", x);
    printf("%%g: %g\n", x);

    return 0;
}
Take Quiz

Cheat Sheet

Quick rules

  • Use %f to print a double with printf
  • float also uses %f in printf
  • Use %lf to read a double with scanf
  • Use %f to read a float with scanf

Common syntax

printf("%f", d);
printf("%.2f", d);
printf("%e", d);
printf("%g", d);

Examples

double d = 1.4;
printf("%f\n", d);    // 1.400000
printf("%.1f\n", d);  // 1.4
printf("%.3f\n", d);  // 1.400

Input rules

float f;
double d;

scanf("%f", &f);
scanf("%lf", &d);

Easy memory trick

  • print: %f for floating-point output
  • scan: %lf for double input

Watch out for

  • %d is for int, not double
  • %f in printf shows 6 decimal places by default
  • printf and scanf do not use floating-point specifiers in the same way

FAQ

Is %lf wrong in printf?

In practice, %lf is treated the same as %f in printf on standard C implementations. But %f is the usual and clearer choice for printing a double.

Why does scanf use %lf for double but printf does not?

Because printf receives promoted arguments, while scanf writes into memory through pointers and must know the exact destination type.

Can I print a float using %f in printf?

Yes. A float is promoted to double when passed to printf, so %f is correct.

What does %f print by default?

It prints 6 digits after the decimal point unless you specify a different precision.

How do I print only 2 decimal places?

Use precision in the format string:

printf("%.2f", value);

Should I always use printf for floating-point output?

For simple console programs, yes. In larger programs, formatting may also be done with logging systems, string formatting helpers, or file output functions such as fprintf.

What happens if I use the wrong format specifier?

The output may be wrong, and in some cases the program may have undefined behavior. Always match the specifier to the expected argument type.

Take Quiz

Mini Project

Description

Build a small console program that reads a few decimal values, calculates their average, and prints the result with different printf floating-point formats. This reinforces the difference between reading with scanf and printing with printf, while giving practice with precision control.

Goal

Create a C program that reads three double values, computes the average, and displays the result using %f, %.2f, and %g.

Requirements

  1. Read three decimal numbers from the user as double values.
  2. Validate that each input was read successfully.
  3. Compute the average of the three values.
  4. Print the average using fixed-point output and custom precision.
  5. Also print the average using %g for compact output.
Take Quiz

Keep learning

Related questions

View more