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
| Specifier | Type in printf | Type in scanf | Example output |
|---|---|---|---|
%d or %i | int | int * | 42 |
%u | unsigned int | unsigned int * | 42 |
%ld | long | long * | 1234567890 |
%lld | long long | long long * | 9000000000 |
%hd | short | short * | 300 |
%f | double (and float, which is promoted) | float * | 3.140000 |
%lf | double | double * | 3.140000 |
%e | double, scientific | float * | 3.140000e+00 |
%g | double, shortest of %f/%e | float * | 3.14 |
%c | int (a character) | char * | A |
%s | char * (a string) | char * (an array) | hello |
%x / %X | unsigned int, hex | unsigned int * | ff / FF |
%o | unsigned int, octal | unsigned int * | 17 |
%p | void * (an address) | — | 0x7ffc10 |
%zu | size_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:
| Example | Meaning | printf of 3.14159 / 42 / "hi" |
|---|---|---|
%.2f | 2 digits after the point | 3.14 |
%8.2f | at least 8 wide, right-aligned | 3.14 |
%-8.2f | left-aligned in 8 | 3.14 |
%5d | at least 5 wide | 42 |
%05d | pad with zeros | 00042 |
%+d | always show the sign | +42 |
%.3s | at most 3 characters of a string | hi |
%*d | width taken from an argument | printf("%*d", 5, 42) → 42 |
#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.0001Run and edit it in the app.
scanf specifics
%d,%f,%sand friends skip leading whitespace (spaces, newlines).%cdoes not — write" %c"with a space to skip it.%sreads 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);.scanfreturns how many items it filled — check it. See Taking Input with scanf.
Gotchas
printf("%d", 3.5)— passing a double to%dprints garbage. Cast:printf("%d", (int) 3.5).printf("%f", 7)— passing an int to%fis just as wrong. Use7.0or(double) 7.printf("%d", sizeof x)—sizeofissize_t; use%zu.printf(user_text)— if the text contains%, printf goes looking for arguments that aren't there. Writeprintf("%s", user_text).- Old Windows runtimes may not understand
%zuor%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?