A Custom Ultra-Small, Ultra-Fast, Zero-Dependency Formatted Output Library for Embedded Systems

<span>printf</span> is actually an ultra-small, ultra-fast, zero-dependency formatted output library specifically designed for embedded systems. The standard libc <span>printf</span> often bloats the code size by over 20 KB on MCUs and may not be thread-safe. This library consolidates all necessary code into <span>printf.c</span>, achieving everything in one file, and can trim features like floating-point and exponential as needed.

What pain points does it solve?

Pain Point Traditional libc <span>printf</span> This tiny printf
Code Size Often > 20 KB Only ~600 lines of source code, a few KB
Dependencies Requires a complete C standard library Zero dependencies, single file
Thread Safety May have race conditions Fully reentrant, thread-safe
Customizability Fixed functionality, cannot remove Can disable floating-point, exponential, etc. via macro switches
Portability Difficulty Requires linking with libc, many platform restrictions Only needs an implementation of <span>_putchar</span>
Debugging/Testing Hard to ensure all formats are correct Over 400 unit tests, high coverage

In summary: If you want to save memory, speed, and stability, choose this.

How easy is it to set up?

  1. 1. Add <span>printf.c</span> and <span>printf.h</span> to your project.
  2. 2. Implement a low-level character output function <span>_putchar</span> (e.g., sending bytes via UART).
    void _putchar(char ch) {
        // Send ch to serial port, screen, or debug output
        UART_SendByte(ch);
    }
  3. 3. Call it just like you would with the standard library:
    printf("Temperature is %0.2f°C\n", temperature);
    sprintf(buf, "ID=%08X", device_id);
  4. 4. Want more flexibility? Use <span>fctprintf</span> to treat any callback as a stream:
    fctprintf(my_log_func, NULL, "Error code: 0x%X\n", err);

If you’re concerned about buffer overflow, it is highly recommended to use <span>snprintf</span>, specifying the maximum buffer length for safety and peace of mind.

Advantages & Disadvantages

Advantages

  • Small Size: Around 600 lines of source code, runs in a few KB.
  • Zero Dependencies: No external libraries required, directly compiled into the MCU.
  • Full Features: Supports <span>%d %u %x %f %e %g %s %c %p</span>, along with complete formatting options like width, precision, and flags.
  • Customizable: Macro switches to disable unnecessary features, further reducing size.
  • Thread Safe: Does not use global static buffers, allowing concurrent calls.
  • Test Coverage: Over 400 test cases, ensuring basic standard compliance.

Disadvantages

  • No Wide Character (wchar_t) Support: Direct printing of wide characters for Chinese requires conversion.
  • Floating Point Support Slightly Increases Code Size: If the MCU lacks hardware floating point, disabling macros will save space.
  • Requires Implementation of <span>_putchar*</span> Output: This may pose a slight barrier for beginners (but most platforms already have UART examples).

ConclusionEmbedded projects often struggle with firmware size due to <span>printf</span><span>, and this tiny printf offers a solution with </span><strong><span>“one line of code + one callback”</span></strong><span>, retaining powerful formatting capabilities while minimizing size. Customizable, zero-dependency, and thread-safe, it meets the stringent requirements for </span><strong><span>code size</span></strong><span>, </span><strong><span>performance</span></strong><span>, and </span><strong><span>reliability</span></strong><span>. If you're struggling with logging, debugging, or UI text on your MCU, give it a try!</span>

Project Address: https://github.com/mpaland/printf

Leave a Comment