nanoprintf:一个超轻量级的 snprintf/vsnprintf 实现,纯 C99 单头文件,无 malloc

想在嵌入式里用 printf,又不想拉来一大堆 libc,堆栈还狂飙?今天给大家安利一个神奇的小家伙——nanoprintf,全篇走口语化,避开那种教科书腔,保证听起来像隔壁老王在给你唠嗑。

什么是 nanoprintf?
简单说,它就是一个超轻量级的 snprintf/vsnprintf 实现,纯 C99 单头文件,无 malloc,用不到 100 字节栈空间。编译出来也就 580–2800 字节(针对 Cortex-M0,取决于你开不开浮点、二进制等功能)。它目的是纠结在“能跑”的最小化,而不是条理清晰的卷福式代码。

它为啥牛?痛点全击破

  • • 嵌入式项目里,<stdio.h> 常常带一堆 syscalls 或者文件描述符,根本用不上;

  • • 想把日志直接发串口、发总线,自己绑个 callback 就行,零 syscall;

  • • 想要更小?禁掉浮点、二进制、写回(%n)、大长度修饰符,编译体积还会再缩水;

  • • 兼容性超好,Clang/GCC/MSVC + UBsan/ASan 都过,32/64 位都打过包;

  • • 最核心的格式化逻辑都在一个 npf_vpprintf 里,虽然看着像大杂烩,但确实省空间。

核心 API 速览

函数

用法 & 作用

npf_snprintf(buf,len,fmt,…)

跟标准 snprintf 一样,填 buf,返回应写总长度

npf_vsnprintf(buf,len,fmt,va)

支持 va_list 的版本

npf_pprintf(putc,ctx,fmt,…)

每打个字符就回调 putc(c,ctx),适合 UART

npf_vpprintf(putc,ctx,fmt,va)

带 va_list 的字符回调版本

简单上手:代码演示
看图不如写码,咱直接上例子。

// 在某个 .c 里先开实现
#define NANOPRINTF_IMPLEMENTATION
// 以下都可按需开启/关闭
// #define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
// #define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1
#include "path/to/nanoprintf.h"

// 串口打印
void uart_putc(char c, void* ctx){
// 你自己的串口发送函数
    my_uart_send((uint8_t)c);
}

void log_to_uart(void){
    npf_pprintf(uart_putc,NULL,
        "温度: %d°C, 电压: %.2fV\n",
        read_temp(), read_voltage());
}

// 缓冲区写入
void build_msg(char* buf, size_t len){
   int used = npf_snprintf(buf, len,
   "ID:%04d 状态:%s", device_id(), status_str());
// 注意返回值 used 是“如果够大能写多少”,不含 '\0'
}

// 解析格式串(进阶)
npf_parse_fmt("Hello %08x",---); // 仅解析不输出

优缺点一览表

优点

缺点

单文件头,Drop-in 即用

源码可读性差,全塞在 #ifdef 汤里

零堆分配、100B 栈,Cortex-M0 下仅几百字节

不支持 %e/%g/%a 科学计数、大多数区域化转换

支持按需编译,浮点、二进制、写回等功能可选

宽字符 %lc/%ls 只能当成 %c/%s 处理

Clang/GCC/MSVC + UBsan/ASan 无警告

配置宏一旦显式指定,就所有宏都得显式指定

并发安全(只要你 callback 做好保护)

没有自带 printf,要自己包一层

适用场景 & 小结

  • • Bootloader、固件里,空间极度紧张,却想保留基本 printf 能力;

  • • 串口、I2C、CAN 总线等无文件概念,只要回调每字节发出去;

  • • 想 DIY 你的轻量级日志库、RPC 框架,或者只要偶尔往缓冲区写格式化字符串;

  • • 如果你不需要科幻的科学计数、区域化、wchar,那真没啥理由不用。

总的来说,nanoprintf 就是那种“能死磕到最小,别奢求漂亮、模块化”的实用主义作品。要是你也是追求极简、上游戏搞固件,就赶紧把它丢进项目里,用 #define NANOPRINTF_IMPLEMENTATION 一键带走。项目地址在这儿求 Star!

项目地址:https://github.com/charlesnicholson/nanoprintf

发表评论