- 1、本文档共12页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
printf在uCOS51上的移植和浮点数显示
asdjf@163.com 2003/10/20
printf函数是C语言里应用最为广泛的函数之一,我们初学C语言时实现的第一个程序《Hello the world》,就包含printf语句。它的应用十分灵活,可以打印各种类型数据,可变数量的变量,表达式,是非常理想的输出函数,广泛用于结果输出,中间变量显示,调试等。然而,编译器将其作为标准库函数,不提供源代码,其本身代码量也偏大,无法实现嵌入式系统按需裁减的要求,并且有些printf库代码不支持重入。
解决方法是把Linux里的相关源码简化后移植到C51里。关键点在于理解变参函数、参数传递规则、浮点数存储格式。
C编译器一般将函数参数按从右至左的顺序依次压入堆栈(C51在使用reentrant关键字后也这么处理),函数内部处理参数变量时直接在堆栈上寻址,局部变量紧跟在参数后面存放,函数返回时出栈,参数和局部变量所占用空间自动释放。例如:
fun(char *fmt,char a,int b long c,float d) reentrant
的堆栈结构如图1所示:
------------------
|float d 4 bytes |
+10 ------------------
|long c 4 bytes |
+6 ------------------
|int b 2 bytes |
+4 ------------------
|char a 1 bytes |
+3 ------------------
|char *fmt 3bytes|
SP+0--------------------
| 局部变量 |
------------------
图1.fun函数参数和局部变量在堆栈里的结构
C51编译器从右向左依次将float/long/int/char/char *压入仿真堆栈,各种数据类型所占空间大小如图1,例如char占1字节,float占4字节等。值得一提的是,常数压栈的格式:0-255按1字节压栈,256-32767压成2字节,32768(8000H)或以上压成4字节,带有l/L结尾的常数占4字节。
上面的函数fun内部可以通过函数名称访问各个变量,C编译器自动把函数名转换成地址,如:访问long c转换成访问SP+6,访问char a转换成访问SP+3等。写成表达式为:
c=0======(SP+6)=0 a=y;=============(SP+3)=y
总之,上面的函数通过显式地指定函数名和数据类型完成参数的传递和访问,内部细节由C编译器完成,对用户透明。
这种方式的好处是表达清晰,结构严谨,屏蔽底层细节;坏处是不够灵活,参数必须在处理前显式确定并固定不变,这给我们用同一函数处理不同情况带来了困难,C的解决方案是引入“变参函数”(详见C语言大全),如下:
fun(char *fmt,...) reentrant
...表示有0到N个可变数量参数,C编译器此时不检查参数匹配,传递参数规律与一般函数相同。如果我们用这个函数取代前一个函数,但仍按前一函数的调用方式调用,那么,参数在堆栈里的位置仍如图1所示。此时,函数形参只有“...”没有具体变量名,如何引用形参变量呢?观察图1堆栈结构可知,如果知道堆栈内第一个参数的起址和每个参数的数据类型及他们的排列顺序,就可以通过指针访问指定的变量。例如:
知道堆栈内第一个参数的起址SP和每个参数的数据类型及排列顺序(char*/char/int/long/float),就可以通过SP,SP+3,SP+4,SP+6,SP+10访问原来必须通过参数名访问的fmt,a,b,c,d变量。写成C语言就是:
fun(yy,y,(int)2,5L,-12.5);
fun(char *fmt,...) reentrant
{
void *p;
p=fmt;
//此时*p指向字符串yy首址,**p是字符串第一个
您可能关注的文档
最近下载
- Excel中如何能破解“撤销工作表保护密码”并获取原始密码.doc VIP
- 2023初中数学培优竞赛例题+练习 专题45 全国初中数学竞赛分类汇编卷(九)四边形综合(简单)(学生版+解析版).doc VIP
- 新时代研究生学术英语综合教程2(崔岭)课后习题答案.pdf VIP
- 第一节、教育学的研究对象及任务.doc
- 2023初中数学培优竞赛例题+练习 专题44 特殊的四边形(学生版+解析版).docx
- 化工产业集中区安全发展规划.doc
- 2023初中数学培优竞赛例题+练习 专题47 一元二次方程(学生版+解析版).docx
- 2023初中数学培优竞赛例题+练习 专题33 三角形的四心(学生版+解析版).docx
- 【读后续写】第01期:读懂原文做3件事(1).pptx VIP
- 技术规范标准医疗机构消毒技术规范医疗机构消毒技术规范.docx VIP
文档评论(0)