printf的封装与实现
1 UART通信协议
1.1 UART通信的物理连接

图1 UART的物理连接
1.2 逻辑电平
用电平表示逻辑1和逻辑0,逻辑1和逻辑0用来组织计算机层面的数据。
1.3 电平标准
根据通讯使用的电平标准不同,串口通讯可分为 TTL标准及 RS-232 标准。
1.4 协议解析
通讯双方需要约定波特率,并约定一致的数据包格式才能保证正常收发数据。
1.4.1 波特率(bps)
单位时间内,发送数据的位数。
1.4.2 数据格式
串口通信一般以起始位作为一帧数据传输的开始,以结束位表示一帧数据传输的结束。每一帧数据一般由起始位、数据位、停止位、校验位组成。
起始位:由1个逻辑0的数据位表示;
停止位:由 0.5、1、1.5或 2个逻辑 1的数据位表示;
校验位(奇校验/偶校验):当为奇校验时,数据位和校验位中,逻辑1的数据位的个数为奇数个;当为偶校验时,数据位和校验位中,逻辑1的数据位的个数为偶数个。

图2 115200,8n1; send 0b01000001
如图2所示,115200bps,则1/115200spb,即每传输一位需要1/115200秒,数据在(1/115200)/2处采样。
2 printf的实现
2.1 标准库中的printf
函数原型:
int printf(const char *format, ...)
返回值:
成功返回实际输出字符数,失败返回-1;
传入参数说明:
format: 固定参数
...: 可变参数;参数的个数不确定,类型不确定;
2.2 可变参数的实现原理
调用子函数,函数的参数最终会以被压入栈中,被函数使用;通过格式控制符,实现对栈中传入参数的读取和使用。
在标准库中的实现:
typedef char* va_list;
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1)) //保证4字节对齐
#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v)) //获取第一个变参在栈中的地址
#define va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) //获取ap所指向的数据,并把ap偏移至下一个变参的地址
#define va_end(ap) (ap = (va_list)0) //使ap指向空,避免野指针

printf(format, arg1, arg2, arg3);参数在栈中的存放
2.3.1 对_INTSIZEOF(n)分析
栈指针总是4字节对齐的,因此使用_INTSIZEOF(n),使变量的大小是4的倍数(实际变量在栈中占据的空间)。
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1)),对这个宏定义有一个形象的比喻:
比方说有一个箱子可以装4个瓶子,
如果我有8个瓶子 ,那么我需要2个箱子;
如果我有10个瓶子呢,我不能说我需要10除4,需要2.5个箱子吧,实际上我需要3个箱子;
那怎么求我实际需要的箱子数呢?
用一个容易理解的公式来求上述问题:
设我的瓶子数为B,我需要的箱子数为C,一个箱子最多可以装A个瓶子。
公式:C =(B+A-1)/ A (舍去余数)
因此,((sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1))相当于C * A。
2.3.2 对va_arg(ap, t)分析
#define va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
这个宏定义实现了两个功能:
a、ap += _INTSIZEOF(t) —— 求下一个参数的指针
b、(*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) —— 取当前参数值,这个宏定义将返回的就是当前参数值
附录:源代码
uart.c —— 波特率:115200

debug_printf.c

printf的封装与实现的更多相关文章
- 由endl对printf和cout的思考
[前言]二者的区别就不介绍了.二者使用方法: printf("%s",a); cout<<a<<endl; endl的作用是什么? 一.endl作用 众所周 ...
- 计算机网络中的帧封装(C实现)
这段时间开始复习计算机网络,看到帧封装这一节,结合以前的课程设计,就用C写了个帧封装的程序,说实话C学的确实不怎么样,实现的时候对于文件操作那部分查了好多资料,下面说说帧封装是啥情况. 学过计算机网络 ...
- va_list可变参数
可变参数函数实现 va_list,va_start,va_arg,va_end va可变参数意思,variable-argument. 1. 头文件及实现 linux中定义在gcc头文件中,stdar ...
- 写一个函数封装printf用作trace
转自http://blog.csdn.net/coder_weisong/article/details/10285291 写一个函数封装printf用作trace 方法一: #inc ...
- 1.import和include区别 2.NSLog 和printf区别 3.创建对象做的事情 4. 类和对象方法比较 5 匿名对象优缺点 6. 封装 7.作用域范围 8.id和instancetype 9.自定义构造方法规范 10.nil和Nil及NULL、NSNull区别
1.import和include的区别: import可以防止头文件的重复包含 2.NSLog 和printf的区别: 1,NSLog可以自动换行, 输出调试信息, printf不能. 2,NSLog ...
- 封装自己的printf函数
#include <stdio.h> #include <stdarg.h> //方式一 #define DBG_PRINT (printf("%s:%u %s:%s ...
- wndows程序设计之书籍知识与代码摘录-封装一个类似printf的messagebox
//----------------------------------------- //本程序展示了如何实现MessageBoxPrintf函数 //本函数能像printf那样格式化输出 //摘录 ...
- 变参标准函数的重新封装,如printf
方法一: #include <stdio.h> #include <stdarg.h> void my_trace(const char *cmd, ...) { printf ...
- 用C语言封装OC对象(耐心阅读,非常重要)
用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...
随机推荐
- AI基础概念
基础概念 epoch:使用训练的全部数据对模型进行一次完整的训练,被成为“一代训练”.当一个完整的数据集通过了神经网络一次并且返回了一次,这个过程称为一次epoch.(也就是说,所有训练样本在神经网络 ...
- java记录5--线程
------------恢复内容开始------------ 1.什么叫程序:是一个严格有序的指令集合.程序规定了完成某一任务时,计算机所需做的各种操作,已经执行顺序. 特点:资源的独占性 执 ...
- nacos集群配置
一. 环境准备 Nacos 依赖 java环境来运行.如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用: 64 bit OS,支持 Lin ...
- nacos作为配置中心兼容xml配置文件
最近公司想要用配置中心,因为公司用的有传统的spring项目,有springboot项目,为了兼容都能够采用配置中心,做了一些尝试,经过比较还是倾向于使用nacos,传统dubbo采用spring方式 ...
- ie9下浏览器 cosole.log()会阻止j下面的s加载
ie9下浏览器 cosole.log()会阻止j下面的s加载,删掉多余的console.log().
- Linux进程管理(二)
目录 Linux进程管理(二) 参考 vmstat命令 top命令 Linux进程管理(二)
- CSP-S 2019 初赛游记
Day 0 上午考了一套毒瘤的数据结构题,考的我心态爆炸SB出题人 晚上考了一套初赛模拟,只考1h,然后我91分,感觉初赛完全没问题? 回寝室后一直在忙活,整理东西什么的,居然将近12点睡? Day ...
- 138、Java内部类之访问内部类的私有属性
01.代码如下: package TIANPAN; class Outer { // 外部类 private String msg = "Hello World !"; class ...
- 一文解读SDN (转)
一. 什么是SDN? SDN字面意思是软件定义网络,其试图摆脱硬件对网络架构的限制,这样便可以像升级.安装软件一样对网络进行修改,便于更多的APP(应用程序)能够快速部署到网络上. 如果把现有的网络看 ...
- eclipse中使用maven创建项目JDK版本默认是1.5
1. 修改maven的settings.xml文件. 添加以下行,jdk版本改为自己需要的版本: <profile> <id>jdk-1.7</id> <ac ...