【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 的 实现步骤的大致方向清楚了);

版权声明:本文为博主原创文章,未经博主允许不得转载。

C打印函数printf的一种实现原理简要分析的更多相关文章

  1. stm32_f103使用gcc编译的环境下printf打印函数的实现

    前记   gcc编译使用的printf打印函数需要的底层函数是和其他编译器不同的,以前的是无法使用的,这里有两种方法,一种是使用gcc库里面的printf函数,自己实现底层IO函数_write.另外一 ...

  2. 嵌入式操作系统---打印函数(printf/sprintf)的实现

    一.打印函数简介 作用:将“给定的内容”按照“指定的格式”输出到“指定目标内”. 打印函数的基本格式: char print_buf[BUF_SIZE]; void printf(const char ...

  3. Linux使用标准IO的调用函数,分3种形式实现

    /*根据cp命令的格式要求,设计一个类cp的功能程序,要求使用标准IO的调用函数,分3种形式实现,字符,行,块.并注意函数功能的分层*/ #include<stdio.h> #includ ...

  4. Objective-C与Swift下的自定义打印函数(Debug和Release)

    1.Objective-C 在使用Objective-C进行开发的过程中,为了Debug会不断的设置打印函数.如下图是我们经常用的,用来测试监听方法的实现与否: NSLog(@"%s&quo ...

  5. Visual Studio C++ MFC界面常用参数更改(改变图标,添加控件,调试打印函数等等)

    背景 需要使用Visual Studio C++做一些界面.此篇文章既是记录Visual Studio C++在调整界面时常常遇见的问题. 正文 一.如何更改窗体图标,以及生成的.exe图标 更改窗体 ...

  6. scala函数定义的四种方式

    最近开始接触scala编程语言,觉得还是比较新的一个东西,虽然说和java比较像,是java的继承者,兼顾面向对象编程和函数式编程的优点,但是,终究是一个新的东西,还是要从最基本的学起.而这当中,函数 ...

  7. 【三支火把】---一份程序看懂C程序printf()的几种常用用法

    闲来继续巩固我的学习之路,今天略微整理了一下,C程序中Printf()的一些常用用法,虽然自己以前好像会,但是不够系统,今天大致整理了一些,先贴上来看看,以后在看到其他,继续补充,希望能帮到一些像我一 ...

  8. IOS学习笔记07---C语言函数-printf函数

    IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...

  9. java 打印空心菱形的两种实现

    第一种实现方式: //打印给定行数的空心菱形 public static void draw(int size){ if (size % 2 == 0) //如果是偶数行变为奇数 { size++; ...

随机推荐

  1. 移动电子商务:五个技术标准与Trustonic TEE解决方案【转】

    转自:http://www.vonwei.com/post/mobileTrustonicTEE.html 转载申明:本站原创,欢迎转载.但转载时请保留原文地址.原文地址:http://www.von ...

  2. java编码,乱码问题详解

    一.常见的编码格式 1.ASCII 基础编码,英文和西欧字符. 用一个字节的低7位表示,一共128个. 0~13是控制字符如换行.回车.删除等,32~126是打印字符,键盘输入. 2.IOS-8859 ...

  3. C++多线程(POSIX)

    #include<iostream> #include<pthread.h> #include<ctime> #include<windows.h> u ...

  4. querySelector和getElementById之间的区别

    一.概述 今天在看js的时候发现里面的代码基本上都是用querySelector()和querySelectorAll()来获取元素,就有点疑惑为什么不用getElementById(),可能也是因为 ...

  5. Springboot如何优雅的解决ajax+自定义headers的跨域请求

    1.什么是跨域 由于浏览器同源策略(同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同.),凡是发 ...

  6. IOS7开发~错误收集

    1. fatal error: file '/Applications/Xcode5-DP.app/Contents/Developer/Platforms/iPhoneSimulator.platf ...

  7. ASIHTTPRequest实现断点续传

    http://blog.csdn.net/daiyelang/article/category/1377418 ASIHTTPRequest可以实现断点续传.网上有一些介绍类似使用:   [reque ...

  8. vue2.0中怎么获取元素

    在元素上添加 v-el:food-wrapper (不用驼峰的写法) vue1版本 报错: vue2版本 (vue2把vue1中的 v-el 改为了 ref vue1 v-el:foods-wrapp ...

  9. Linux学习之十三-vi和vim编辑器及其快捷键

    vi和vim编辑器及其快捷键 1.vi与vim区别 它们都是多模式编辑器,不同的是vim 是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面. vim的这些优势主要体现在以下几个方 ...

  10. centos 7 安装五笔输入法

    centos 7 安装五笔输入法 [a@endv ~]$ yum search wubi 已加载插件:fastestmirror, langpacks Loading mirror speeds fr ...