Skip to main content

C Format Strings: A Practical Printing Guide

Pascal Spörri
Author
Pascal Spörri
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
#

TypeFormat StringNotes
char%dPromoted to int.
short%dPromoted to int.
int%dMinimum width: 16-bit.
long%ldMinimum width: 32-bit.
long long%lldMinimum width: 64-bit.
int8_t%dPromoted to int.
int16_t%dPromoted to int.
int32_t%ldCast to long required.
int64_t%lldCast to long long required.
unsigned char%dPromoted to int.
unsigned short%uPromoted to int.
unsigned int%uMinimum width: 16-bit.
unsigned long%luMinimum width: 32-bit.
unsigned long long%lluMinimum width: 64-bit.
uint8_t%u or %dPromoted to int.
uint16_t%uPromoted to int.
uint32_t%luCast to unsigned long required.
uint64_t%lluCast to unsigned long long required.
size_t%zuPlatform-dependent unsigned type.
float%f or %gPromoted to double for printf.
double%f or %gStandard floating-point format.
void *%pPointer address format.
hex(uint8_t)%x or %XLower/upper case hex.
hex(uint16_t)%x or %XLower/upper case hex.
hex(uint32_t)%lx or %lXCast to unsigned long.
hex(uint64_t)%llx or %llXCast to unsigned long long.

For more information, refer to the POSIX fprintf man page.