详细解析 minprintf 的最小实现
Link: https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628
翻看这本书,找寻printf的实现,书中给出一个最小实现,下面解析之。

这是C语言之父写的书
丹尼斯·麦卡利斯泰尔·里奇(英语:Dennis MacAlistair Ritchie,1941年9月9日—2011年10月12日),美国计算机科学家。黑客圈子通常称他为“dmr”[4]。他是C语言的创造者、Unix操作系统的关键开发者[5][6][7][8],对计算机领域产生了深远影响,并与肯·汤普逊同为1983年图灵奖得主。https://zh.wikipedia.org/wiki/%E4%B8%B9%E5%B0%BC%E6%96%AF%C2%B7%E9%87%8C%E5%A5%87
代码展示了一个简化版的 printf 函数实现,名为 minprintf,能够处理有限的格式化输出功能,包括整数 (%d)、浮点数 (%f) 和字符串 (%s)。以下是对代码的逐步解析,并特别关注 *++p 的语法。
代码核心功能
void minprintf(char *fmt, ...) {va_list ap; char *p, *sval;int ival;double dval;va_start(ap, fmt); // 初始化可变参数列表for (p = fmt; *p; p++) { // 遍历格式化字符串if (*p != '%') { // 如果不是格式说明符,直接输出字符putchar(*p);continue;}switch (*++p) { // 获取格式说明符case 'd':ival = va_arg(ap, int); // 提取 int 参数printf("%d", ival);break;case 'f':dval = va_arg(ap, double); // 提取 double 参数printf("%f", dval);break;case 's':for (sval = va_arg(ap, char *); *sval; sval++) // 输出字符串putchar(*sval);break;default:putchar(*p); // 如果不是已知格式说明符,直接输出break;}}va_end(ap); // 清理可变参数
}
重点语法解析:*++p
在代码中,*++p 是一个关键的语法结构,其作用是:
++p:将指针p向前移动一个字符,指向下一个位置。*++p:解引用新位置的字符,即获取格式说明符。
完整流程:
- 如果当前字符为
'%',通过++p跳过'%',检查其后面的格式说明符(如'd'、'f'、's'等)。 - 解引用
*++p获取格式说明符,用于switch语句处理。
示例与分析
假设有如下调用:
minprintf("Value: %d, Name: %s, Score: %f\n", 42, "Alice", 95.5);
1. 处理流程
p = "Value: %d, Name: %s, Score: %f\n"(fmt的内容)- 遍历字符串,遇到普通字符(如
'V'、'a'等)时,直接输出。 - 遇到
'%'时,调用*++p获取后续格式说明符并处理。
2. *++p 语法的作用
- 当
p指向'%'时:++p将指针移动到下一位置,即'd'。*++p解引用,返回'd',交由switch处理。
- 以此类推,后续会分别处理
'%s'和'%f'。
3. 每一步指针状态
- 起始:
p指向V,输出V,指针移动。 - 遇到
%:调用*++p,跳过%,获取下一个字符'd'。 - 解析
d后输出42,继续处理后续字符。
示例输出分析
对于上述代码调用:
minprintf("Value: %d, Name: %s, Score: %f\n", 42, "Alice", 95.5);
步骤:
- 输出普通字符:
Value:。 - 遇到
%d:*++p解引用,获取d。- 提取整数
42,格式化输出为42。
- 输出普通字符:
, Name:。 - 遇到
%s:*++p解引用,获取s。- 提取字符串
"Alice",逐字符输出为Alice。
- 输出普通字符:
, Score:。 - 遇到
%f:*++p解引用,获取f。- 提取浮点数
95.5,格式化输出为95.500000(默认 6 位小数)。
- 输出换行符
\n。
最终输出:
Value: 42, Name: Alice, Score: 95.500000
总结
*++p的作用:++p移动指针到下一字符。*++p解引用获取当前字符,用于格式说明符处理。
- 代码实现思路:
- 遍历格式化字符串,按字符解析。
- 对于普通字符,直接输出。
- 遇到
%时,通过*++p获取说明符,并提取参数处理。
- 关键点:
va_list的使用使得minprintf能够处理可变参数。*++p高效实现格式说明符解析,是简化实现的核心。
这段代码简单直观,体现了 C 语言实现格式化输出的核心思想,是理解 printf 工作原理的重要案例。
后记
2025年1月27日于山东日照。
