首先:Keil和GCC底层printf函数走的是两条完全不同的路线

Keil MDK + 勾选MicroLIB

pinrtf -> 格式化拆分字符 -> fputc(ch,FILE*) -> 串口发送

MicroLIB库强制所有printf输出走fputc,所以只要重写fputc,printf百分百生效。

这是针对Keil的。

ARM-GCC+newlib-nano+nosys.specs(Clion+Cmake环境)

Newly-nano为了极致精简FLASH,砍掉冗余代码,重构了printf底层链路,不再默认走fputc,出现了两条分枝优先级。

优先级: _io_putchar > _write > fputc

开启nano.specs后,printf优先走最精简路径:_io_putchar,直接跳过fputc,所以如果我重写fputc等于白写。库根本不进入这个函数,串口自然没有数据。

注:newlib-nano 为了省 Flash,砍掉文件流 FILE 缓冲层,设计了**单字符直通接口__io_putchar**:

只要用户实现这个函数,nano 的 printf 直接逐个字符丢进它,绕过 FILE 结构体、绕过 fputc、绕过_write,代码体积最小(这就是你加完立刻出数据的原因)。