Formatted Output with printf

printf turns values into text using a format string: ordinary characters are printed as they are, and each % specifier is replaced by the next argument. Widths, precision and flags let you line up tables and control exactly how numbers look.

Conversion specifiers

SpecifierTypeExample output
%d / %iint-42
%uunsigned int42
%ld, %lld, %lu, %llulong, long long and unsigned versions9000000000
%zusize_t16
%f, %e, %gdouble (and float)3.140000
%ccharacterA
%sstringhello
%x, %X, %ounsigned, in hex / octalff
%ppointer (address)0x16f…
%%a literal %%

Width and alignment

A number after % sets the minimum width. Values are right-aligned; a - flag left-aligns:

C
#include <stdio.h>

int main(void) {
    printf("[%5d]\n", 42);
    printf("[%-5d]\n", 42);
    printf("[%05d]\n", 42);
    printf("[%10s]\n", "right");
    printf("[%-10s]\n", "left");
    return 0;
}
Output
[   42]
[42   ]
[00042]
[     right]
[left      ]

The 0 flag pads numbers with zeros — useful for times and IDs.

Precision

After a dot, the precision means decimal places for floating point, and maximum characters for strings:

C
#include <stdio.h>

int main(void) {
    double pi = 3.14159265;
    printf("%.0f | %.2f | %.5f\n", pi, pi, pi);
    printf("%8.3f|\n", pi);
    printf("%.3s\n", "abcdefgh");
    return 0;
}
Output
3 | 3.14 | 3.14159
   3.142|
abc

Rounding uses the usual rules, so %.2f of 3.14159 gives 3.14.

Flags

FlagEffectExample
-Left-align within the width%-8s
0Pad numbers with zeros%03d → 007
+Always show the sign%+d → +5
spaceSpace before positive numbers% d → 5
#Prefix hex with 0x, octal with 0%#x → 0xff
C
#include <stdio.h>

int main(void) {
    printf("%+d %+d\n", 5, -5);
    printf("%#x %#o\n", 255, 8);
    printf("%02d:%02d:%02d\n", 9, 5, 3);
    return 0;
}
Output
+5 -5
0xff 010
09:05:03

A formatted table

C
#include <stdio.h>

int main(void) {
    printf("%-12s %5s %9s\n", "Item", "Qty", "Price");
    printf("%-12s %5d %9.2f\n", "Notebook", 4, 3.5);
    printf("%-12s %5d %9.2f\n", "Pen", 10, 1.2);
    printf("%-12s %5d %9.2f\n", "Backpack", 1, 39.9);
    return 0;
}
Output
Item           Qty     Price
Notebook         4      3.50
Pen             10      1.20
Backpack         1     39.90

Width from an argument

A * takes the width (or precision) from the argument list — handy when it's only known at run time:

C
#include <stdio.h>

int main(void) {
    for (int width = 1; width <= 4; width++) {
        printf("[%*d]\n", width * 2, width);
    }
    return 0;
}
Output
[ 1]
[   2]
[     3]
[       4]

Getting the types right

The specifier must match the argument's type. printf can't check this itself, so a mismatch is undefined behaviour — but compilers do check format strings and warn:

C
#include <stdio.h>

int main(void) {
    double price = 9.99;
    long long views = 12345678901;
    printf("%d\n", price);
    printf("%d\n", views);
    return 0;
}
Compiler warnings
main.c:6:20: warning: format specifies type 'int' but the argument has type 'double' [-Wformat]
main.c:7:20: warning: format specifies type 'int' but the argument has type 'long long' [-Wformat]

Formatting into a string

snprintf writes the formatted text into a character array instead of the screen. It never writes more than the size you give, and returns the length the full text would have had:

C
#include <stdio.h>

int main(void) {
    char label[16];
    int needed = snprintf(label, sizeof label, "Order #%05d", 731);
    printf("%s (%d characters)\n", label, needed);

    int long_needed = snprintf(label, sizeof label, "Customer: %s", "Alexandra Petrova");
    printf("%s (needed %d)\n", label, long_needed);
    return 0;
}
Output
Order #00731 (12 characters)
Customer: Alexa (needed 27)

When the result doesn't fit, it's cut off safely and still ends with the string terminator. Avoid the older sprintf, which has no size limit and can overflow the array.

Printing to standard error

Error messages should go to stderr, a separate output stream, so they still appear when normal output is redirected to a file. Use fprintf:

C
fprintf(stderr, "Error: could not open %s\n", filename);

Try it yourself

Print a multiplication table for 1 to 5, with each number right-aligned in a column 4 characters wide.

Try it yourself · main.c
Edit the code, copy it into main.c, then compile and run it with cc -std=c17 -Wall main.c -o main && ./main. How to set up a C compiler
Output
   1   2   3   4   5
   2   4   6   8  10
   3   6   9  12  15
   4   8  12  16  20
   5  10  15  20  25