Skip to content
FollowtheDamnCode

Reference: Format Specifiers

printf and scanf codes, widths, precision, and flags.

4 minute read

Big idea

A format specifier is the %… code in a printf or scanf string that says how to print or read one value. The specifier must match the type of its argument — a mismatch is undefined behaviour, not just ugly output.

The main specifiers

SpecifierType in printfType in scanfExample output
%d or %iintint *42
%uunsigned intunsigned int *42
%ldlonglong *1234567890
%lldlong longlong long *9000000000
%hdshortshort *300
%fdouble (and float, which is promoted)float *3.140000
%lfdoubledouble *3.140000
%edouble, scientificfloat *3.140000e+00
%gdouble, shortest of %f/%efloat *3.14
%cint (a character)char *A
%schar * (a string)char * (an array)hello
%x / %Xunsigned int, hexunsigned int *ff / FF
%ounsigned int, octalunsigned int *17
%pvoid * (an address)—0x7ffc10
%zusize_t (from sizeof, strlen)size_t *8
%%a literal %a literal %%

The one asymmetry to remember: printf uses %f for double; scanf needs %lf for double.

Width, precision, and flags

The full shape is %[flags][width][.precision]specifier:

ExampleMeaningprintf of 3.14159 / 42 / "hi"
%.2f2 digits after the point3.14
%8.2fat least 8 wide, right-aligned 3.14
%-8.2fleft-aligned in 83.14
%5dat least 5 wide 42
%05dpad with zeros00042
%+dalways show the sign+42
%.3sat most 3 characters of a stringhi
%*dwidth taken from an argumentprintf("%*d", 5, 42) → 42
Printing a neat table
#include <stdio.h>

int main(void) {
    const char *names[] = {"Tea", "Coffee", "Hot chocolate"};
    double prices[] = {1.5, 2.25, 3};
    for (int i = 0; i < 3; i++) {
        printf("%-14s %6.2f\n", names[i], prices[i]);
    }
    printf("%05d %+d %x %X %o %%\n", 42, 42, 255, 255, 8);
    printf("%g %g\n", 1234.5, 0.0001);
    return 0;
}
output
Tea              1.50
Coffee           2.25
Hot chocolate    3.00
00042 +42 ff FF 10 %
1234.5 0.0001

Run and edit it in the app.

scanf specifics

  • %d, %f, %s and friends skip leading whitespace (spaces, newlines). %c does not — write " %c" with a space to skip it.
  • %s reads one word and stops at whitespace. Always give a width one less than the array: char w[20]; scanf("%19s", w);.
  • %[^\n] reads everything up to a newline (a whole line, spaces included): scanf(" %99[^\n]", line);.
  • scanf returns how many items it filled — check it. See Taking Input with scanf.

Gotchas

  • printf("%d", 3.5) — passing a double to %d prints garbage. Cast: printf("%d", (int) 3.5).
  • printf("%f", 7) — passing an int to %f is just as wrong. Use 7.0 or (double) 7.
  • printf("%d", sizeof x) — sizeof is size_t; use %zu.
  • printf(user_text) — if the text contains %, printf goes looking for arguments that aren't there. Write printf("%s", user_text).
  • Old Windows runtimes may not understand %zu or %lld; recent ones do.

Which reads a double with scanf?

Key terms

  • Format string — The text with % codes that printf/scanf follow.
  • Specifier — The letter(s) after % saying the type: d, f, s, …
  • Width / precision — Minimum field width, and digits after the point (or max characters for %s).
  • Flag — - (left-align), 0 (zero-pad), + (show sign), and others.

Check yourself

Which specifier prints a size_t, like the result of sizeof?

What does printf("%05.1f", 3.14159) print?