A practical guide to choosing the right C format specifiers for safe, portable, and readable output.
C format strings can be confusing, especially when dealing with cross-platform code or multiple compilers. This guide offers a practical reference for choosing the correct format specifier when printing various C types, including standard fixed-width integers and platform-specific types like size_t.
Format String Decision Tree#
Assumption: You need to print a value with a size of 16, 32, or 64 bits using C99 format strings.
- Up to 16 bits: Use
%dfor signed and%ufor unsigned. No casting needed. - 32-bit values: Use
%ld(signed) or%lu(unsigned). Cast tolongorunsigned long. - 64-bit values: Use
%lld(signed) or%llu(unsigned). Cast tolong longorunsigned long long. size_t: Use%zu.- Hexadecimal:
- Up to 16-bit: Use
%xor%X. - 32-bit: Use
%lxor%lX. Cast tounsigned long. - 64-bit: Use
%llxor%llX. Cast tounsigned long long.
- Up to 16-bit: Use
Common Data Types and Format Strings#
| Type | Format String | Notes |
|---|---|---|
char | %d | Promoted to int. |
short | %d | Promoted to int. |
int | %d | Minimum width: 16-bit. |
long | %ld | Minimum width: 32-bit. |
long long | %lld | Minimum width: 64-bit. |
int8_t | %d | Promoted to int. |
int16_t | %d | Promoted to int. |
int32_t | %ld | Cast to long required. |
int64_t | %lld | Cast to long long required. |
unsigned char | %d | Promoted to int. |
unsigned short | %u | Promoted to int. |
unsigned int | %u | Minimum width: 16-bit. |
unsigned long | %lu | Minimum width: 32-bit. |
unsigned long long | %llu | Minimum width: 64-bit. |
uint8_t | %u or %d | Promoted to int. |
uint16_t | %u | Promoted to int. |
uint32_t | %lu | Cast to unsigned long required. |
uint64_t | %llu | Cast to unsigned long long required. |
size_t | %zu | Platform-dependent unsigned type. |
float | %f or %g | Promoted to double for printf. |
double | %f or %g | Standard floating-point format. |
void * | %p | Pointer address format. |
hex(uint8_t) | %x or %X | Lower/upper case hex. |
hex(uint16_t) | %x or %X | Lower/upper case hex. |
hex(uint32_t) | %lx or %lX | Cast to unsigned long. |
hex(uint64_t) | %llx or %llX | Cast to unsigned long long. |
For more information, refer to the POSIX fprintf man page.
