TRT
Sign in
easyFoundationsdebugging

Why does a mismatched printf format specifier cause undefined behavior instead of automatic type conversion in C?

Explain how variadic functions like printf read arguments from registers or the stack blindly using the format string without compile-time type metadata.

TRT practice prompt — not a verified question from a named employer.

The Runtime Theory Team2 min read
Learn it firstAnatomy of a C Program and Formatted I/OExplore program entry points from crt0 and _start to main, inspect process exit codes, and master buffered standard I/O streams.

A strong answer

In C, printf(const char *format, ...) is a variadic function. For the fixed parameter format, the compiler knows the exact type (const char *) and checks it. For the ... arguments, C passes the raw values in CPU registers or on the call stack without any runtime type tags. At runtime, printf has no way to inspect the actual types of the arguments passed to it; it blindly trusts the % specifiers inside the format string to decide which register bank to read (integer/pointer registers vs floating-point XMM registers on x86-64) and how many bytes to consume (4 bytes vs 8 bytes).

If you pass an int (42) with %s, printf reads the integer value 42, interprets it as a 64-bit memory address (0x2a), and tries to dereference it to print a null-terminated string—immediately triggering a segmentation fault. If you pass a double with %d on x86-64 System V ABI, printf reads from the next general-purpose integer register instead of the floating-point XMM register where the double was actually placed, printing unrelated register garbage and shifting the argument cursor for every subsequent % specifier in the call.

What the interviewer is listening for

  • Explains that C variadic functions (...) strip static type information at runtime and rely entirely on the format string to decode registers and stack slots.
  • Mentions hardware calling convention details (such as integer registers vs floating-point registers, or 32-bit vs 64-bit widths).
  • Notes that -Wall -Wformat allows gcc and clang to statically check literal format strings against the argument list at compile time.

Common mistakes

  • Assuming printf("%f", 42) automatically converts the int 42 to 42.0 the way a regular non-variadic function parameter void foo(double x) does.
  • Passing a user-controlled string directly as the first argument printf(buf) instead of printf("%s", buf), which allows an attacker to inject %x or %n format specifiers to read or write stack memory.
  • Using %d instead of %zu for size_t or %ld/%lld for 64-bit integers.

This answer walks

Practice follow-ups

  1. 01What does the C compiler's default argument promotion rule do to float and char arguments passed to printf?
  2. 02Why is printf(user_input) without a '%s' format string a critical security vulnerability?

Not started

Sign in to save your learning progress.

Sign in to save