C打印函数printf的一种实现原理简要分析

【0】README


【1】printf函数代码分析:

https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/p309/printf.c

  • P1)line66: va_list arg = (va_list)((char*)(&fmt) + 4); 要知道,对于C函数的调用,压栈顺序是从右参数往左边参数压栈,最右边参数最先压栈,最左边参数最后压栈;当然, (&fmt+4)指向的是 printf参数列表中 “…” 的首地址, 而“…” 代表的是参数列表(低地址到高地址,因为压栈顺序就是从高地址到低地址压栈):MAG_CH_ASSERT, exp, file, base_file, line ;
  • P2)结合以上叙述,我们得到 buf 就是个字符串数组(可以看做缓冲区)、 fmt = “%c assert(%s) failed: file: %s, base_file: %s, ln%d” 、arg = MAG_CH_ASSERT, exp, file, base_file, line 五个参数列表(即长度为5的20字节数组,每个地址4个字节);

【2】vsprintf 函数代码分析:

https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/p309/vsprintf.c

  • V1)line68: 调用 vsprintf 函数,同样的,参数压栈顺序是从右往左压栈, 我们看看vsprintf 的源码, 结合源码,我们的分析如下:

    • V1.1)line57~60 :非找到 fmt 中的 % 不可(%是定义输出格式的标识符), 且fmt 的字符是一个一个copy 到buf 的;
    • V1.2)line87~113:从参数列表 p_next_arg = args 中 抽取出 格式字符串,用q = inner_buf 来存储这些参数值;(显然,i2a()函数是 数字输出的不同进制的转换,16进制、10进制等),p_next_arg += 4; p_next_arg 为什么自加4 ,不用我多说了吧;
    • V1.3)line119~122:用inner_buf 存储的格式输出值 去填充 %定义的格式输出;
  • V2)再看看 vsprintf 对于 输出格式宽度是如何处理的?如%10d,等等;

    • V2.1)line62 :将align_nr 初始化为 0;
    • V2.2)line67~77: 是在 对 %下一个字符出现的可能情况的处理: 如果有两个 %% 并排,则表明输出为%、如果为0,待会cs=0、如果是其他情况,cs=空格;
    • V2.3)line78~82: 是在对 % 下一个字符是数字(打印宽度)的处理;
    • V2.4)line115~118:将cs 的值赋给 缓冲区 buf, 这里应该是把空格赋值过去,以填充打印宽度(说实话,这里我也没有好懂, 不过printf 的 实现步骤的大致方向清楚了);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值