Skip to main content

C Format Strings: A Practical Printing Guide

Pascal Spörri
Author
Pascal Spörri
Table of Contents
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 %d for signed and %u for unsigned. No casting needed.
  • 32-bit values: Use %ld (signed) or %lu (unsigned). Cast to long or unsigned long.
  • 64-bit values: Use %lld (signed) or %llu (unsigned). Cast to long long or unsigned long long.
  • size_t: Use %zu.
  • Hexadecimal:
    • Up to 16-bit: Use %x or %X.
    • 32-bit: Use %lx or %lX. Cast to unsigned long.
    • 64-bit: Use %llx or %llX. Cast to unsigned long long.

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.