%[flags][min field width][precision][length]conversion specifier
----- --------------- --------- ------ -------------------
\ #,* .#, .* / \
\ / \
#,0,-,+, ,',I hh,h,l,ll,j,z,L c,d,u,x,X,e,f,g,s,p,%
------------- --------------- -----------------------
# | Alternate, hh | char, c | unsigned char,
0 | zero pad, h | short, d | signed int,
- | left align, l | long, u | unsigned int,
+ | explicit + - sign, ll | long long, x | unsigned hex int,
| space for + sign, j | [u]intmax_t, X | unsigned HEX int,
' | locale thousands grouping, z | size_t, e | [-]d.ddde±dd double,
I | Use locale's alt digits t | ptrdiff_t, E | [-]d.dddE±dd double,
L | long double, ---------=====
if no precision => 6 decimal places / f | [-]d.ddd double,
if precision = 0 => 0 decimal places _____/ g | e|f as appropriate,
if precision = # => # decimal places G | E|F as appropriate,
if flag = # => always show decimal point s | string,
..............------
/ p | pointer,
if precision => max field width / % | %
printf format strings
I copied this excellent quick reference guide from Pádraig Brady at PixelBeat lest it should go offline at some point in the future.