C打印函数printf的一种实现原理简要分析
【0】README
- 0.1)本文旨在对 printf 的 某一种 实现 原理进行分析,做了解之用;
- 0.2) vsprintf 和 printf.c 的源码,参见
https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/p309
【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 的 实现步骤的大致方向清楚了);
版权声明:本文为博主原创文章,未经博主允许不得转载。
C打印函数printf的一种实现原理简要分析的更多相关文章
- stm32_f103使用gcc编译的环境下printf打印函数的实现
前记 gcc编译使用的printf打印函数需要的底层函数是和其他编译器不同的,以前的是无法使用的,这里有两种方法,一种是使用gcc库里面的printf函数,自己实现底层IO函数_write.另外一 ...
- 嵌入式操作系统---打印函数(printf/sprintf)的实现
一.打印函数简介 作用:将“给定的内容”按照“指定的格式”输出到“指定目标内”. 打印函数的基本格式: char print_buf[BUF_SIZE]; void printf(const char ...
- Linux使用标准IO的调用函数,分3种形式实现
/*根据cp命令的格式要求,设计一个类cp的功能程序,要求使用标准IO的调用函数,分3种形式实现,字符,行,块.并注意函数功能的分层*/ #include<stdio.h> #includ ...
- Objective-C与Swift下的自定义打印函数(Debug和Release)
1.Objective-C 在使用Objective-C进行开发的过程中,为了Debug会不断的设置打印函数.如下图是我们经常用的,用来测试监听方法的实现与否: NSLog(@"%s&quo ...
- Visual Studio C++ MFC界面常用参数更改(改变图标,添加控件,调试打印函数等等)
背景 需要使用Visual Studio C++做一些界面.此篇文章既是记录Visual Studio C++在调整界面时常常遇见的问题. 正文 一.如何更改窗体图标,以及生成的.exe图标 更改窗体 ...
- scala函数定义的四种方式
最近开始接触scala编程语言,觉得还是比较新的一个东西,虽然说和java比较像,是java的继承者,兼顾面向对象编程和函数式编程的优点,但是,终究是一个新的东西,还是要从最基本的学起.而这当中,函数 ...
- 【三支火把】---一份程序看懂C程序printf()的几种常用用法
闲来继续巩固我的学习之路,今天略微整理了一下,C程序中Printf()的一些常用用法,虽然自己以前好像会,但是不够系统,今天大致整理了一些,先贴上来看看,以后在看到其他,继续补充,希望能帮到一些像我一 ...
- IOS学习笔记07---C语言函数-printf函数
IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...
- java 打印空心菱形的两种实现
第一种实现方式: //打印给定行数的空心菱形 public static void draw(int size){ if (size % 2 == 0) //如果是偶数行变为奇数 { size++; ...
随机推荐
- 【jetty】jetty服务器的使用
1.下载jetty服务器: http://www.eclipse.org/jetty/previousversions.html 2.下载后解压:
- MySQL完整备份,还原
# 备份 添加编码 --default-character-set=utf8 防止中文乱码 把.sql文件导入MySQL, 汉字出现乱码?在.sql文件头中添加:set names 'gbk'; 或 ...
- javascript 获取焦点和失去焦点事件
利用传参的方式提高方法的复用性 这里涉及到JavaScript的字符串拼接操作 </tr> <<tr height="40px"> <td> ...
- (5)centos图形界面安装
1.登录 2.先安装MATE可视化桌面 yum groups install "MATE Desktop" 选择y 3.安装X Window System:图形接口 yum gro ...
- SpringMVC_01:创建运行环境(Maven)
Maven 环境下配置: 1.新建MavenProject,打包选线根据情况选择jar war和pom jar:打包为jar包,主要用于被其他项目引用 war:打包为war包,可直接运行于服务器 po ...
- 全栈一路坑(4)——创建博客的API
上一篇博客:全站之路一路坑(3)——使用百度站长工具提交站点地图 这一篇要搭建一个API平台,一是为了给博客补充一些功能,二是为以后做APP提供数据接口. 首先需要安装Django REST Fram ...
- 使用Python来编写一个简单的感知机
来表示.第二个元素是表示期望输出的值. 这个数组定义例如以下: training_data = [ (array([0,0,1]), 0), (array([0,1,1]), 1), (arra ...
- 【前端阅读】——《程序员思维修炼》摘记&读后感&思维导图
前言:这是一本介绍如何用脑的书,并从思维的角度(以程序员为例),介绍如何从新手成为专家.作者带领着读者(我)共同经历一次有关认知科学.神经学.学习和行为理论的旅程,探索人类大脑令人 惊奇的工作的机制, ...
- 转: Gradle:Gradle入门
from: http://blog.csdn.net/p106786860/article/details/50422463
- hdu 5339 Untitled【搜索】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5339 题意:一个整数a 和一个数组b.问你能否在b中取出r个元素排列组成c数组满足a%c1%c1%-. ...