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
| Specifier | Type | Example output |
|---|---|---|
%d / %i | int | -42 |
%u | unsigned int | 42 |
%ld, %lld, %lu, %llu | long, long long and unsigned versions | 9000000000 |
%zu | size_t | 16 |
%f, %e, %g | double (and float) | 3.140000 |
%c | character | A |
%s | string | hello |
%x, %X, %o | unsigned, in hex / octal | ff |
%p | pointer (address) | 0x16f… |
%% | a literal % | % |
Width and alignment
A number after % sets the minimum width. Values are right-aligned; a - flag left-aligns:
#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; }
[ 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:
#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; }
3 | 3.14 | 3.14159 3.142| abc
Rounding uses the usual rules, so %.2f of 3.14159 gives 3.14.
Flags
| Flag | Effect | Example |
|---|---|---|
- | Left-align within the width | %-8s |
0 | Pad numbers with zeros | %03d → 007 |
+ | Always show the sign | %+d → +5 |
| space | Space before positive numbers | % d → 5 |
# | Prefix hex with 0x, octal with 0 | %#x → 0xff |
#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; }
+5 -5 0xff 010 09:05:03
A formatted table
#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; }
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:
#include <stdio.h> int main(void) { for (int width = 1; width <= 4; width++) { printf("[%*d]\n", width * 2, width); } return 0; }
[ 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:
#include <stdio.h> int main(void) { double price = 9.99; long long views = 12345678901; printf("%d\n", price); printf("%d\n", views); return 0; }
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:
#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; }
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:
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.
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