ImageVerifierCode 换一换
格式:DOC , 页数:5 ,大小:82KB ,
资源ID:3259045      下载积分:20 文钱
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,省得不是一点点
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.wenke99.com/d-3259045.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C51参数可变函数.doc)为本站会员(11****ws)主动上传,文客久久仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知文客久久(发送邮件至hr@wenke99.com或直接QQ联系客服),我们立即给予删除!

C51参数可变函数.doc

1、C51 中的参数可变函数作为引导的例子:假设要编写一个函数,来求 n 个数中最大的一个。函数的声明像下面这样 :unsigned char max( unsigned n , ) ;本文的目标就是实做这个函数。C 语言栈空间的处理方式:我们很容易看懂这样的代码int sum ( int a ,int b )return ( a + b ) ;void main ( void )int x ;x = sum ( 1 , 2 ) ; /*子函数的调用和返回*/While( 1 ) ; 每一次子函数的调用和返回就伴随着一系列的压栈和出栈,但是“内存不可以泄露”,所以子函数返回后栈指针应该恢复到原来的

2、位置,如下图所示:有两种修正栈的办法:一种是在子函数 sum 内进行处理,另一种在调用子函数 sum 结束的地方处理。这也就是 C 语言函数的栈空间处理的两种方式_cdecl 和_stdcall ,您可以把_cdecl 和_stdcall 想象成两个函数,一调用就修正栈指针,如下图_stdcall 方式 sum 函数一旦编写好以后,修正栈的方法就固定了,以后函数的形参个数不能随意变化。如下图所示:这个函数在调用结束后要把盏指针回调 3 个单位,调节指针的工作固定在 sum 子函数的代码内。_cdecl 方式 sum 函数内不做修正栈的工作,每次调用 sum 函数当返回时,编译器都重新帮助 su

3、m 函数再修正一次栈空间,这样就允许了 sum 函数形参个数变化,反正这时 sum 函数又不操心入栈出栈的问题,它只关心运算处理,编译器知道这次调用入栈了多少,应该出栈多少,如下图示:_stdcall 方式节约了 ROM(计算机专业的人叫代码段),但是却让 sum 函数的形参个数不可以变化。_cdecl 方式浪费了 ROM,但是函数的形参个数可以变化。所以我们在 VC+里会看到 printf 这样重要的函数,都是_cdecl 方式的,但是动态链接库的函数一般都是_stdcall 方式的。前者是实际需要,形参必须可以变化;后者因为大量被使用,必须考虑节约 ROM(代码段)。但是在单片机里大家不必

4、操心这些,KeilC51 有自己的入栈出栈方式,参数可变函数能够成功运行。栈的指针:想象一下假设我们编写好了一个参数可变函数,然后去调用它为我们工作。就像这样 function( a , b , c , d , e ),调用前形式参数被压入栈内,在 function 代码内部可以用栈指针去寻找这些参数,然后去使用。一提到栈的指针,大家马上就想到了 sp,但是这样不好。要动用汇编指令,更麻烦的是汇编和 C 语言的结合,这是我们不想看到的场面。C 语言里有其他办法解决这个问题,那就是利用标准库 stdarg.h。这里面的一个数据类型和三个 “函数”是我们最关心的:va_list /注意这是一个数据

5、类型,就如同 charva_start( 形参 1 ,形参 2 ) ;va_arg( 形参 1 ,形参 2 ) ;va_end( 形参 ) ;它们的用途马上就解释。实做 unsigned char max( unsigned n , )函数:这个函数就像他的名字所描述的一样,求 n 个数中最大的一个。假设我们编写好了这个函数,我们就可以去调用了:void main( void )unsigned char M ;M = max( 5 , 20 , 45 , 55 , 80 , 95 );while(1); /51 单片机停机M 自然是返回 95,调用这个函数前,5、20、45 、55、80、9

6、5 先被压栈,如下图所示:要操作这些数据,我们需要一个指向栈空间的指针 pStack,我们可以利用下面方法定义这个指针:va_list pStack;下面我们想让 pStack 指向 20,如下图:方法是,调用函数 va_start( pStack , n ) 。您也许很诧异倒低 n 是什么,那么我把全部的代码拷贝过来给您看看吧,它是这样的:va_start( pStack , n )很古怪,但是这个函数确实就是这么用的 ,这倒不是需要 n 的值,而是需要 n 这个符号。这样pStack 马上就指向了 n 后续的参数。然后您一定想引用这个指针(*pStack)了吧?不行,都不知道 pStack

7、 指向了什么类型的数据。我们需要利用函数va_arg( pStack , unsigned char ) ;这个函数依然很古怪, (1) 这个函数使 pStack 感觉自己指向的是 unsigned char 类型的数据(2) 这个函数把栈指针 pStack 所指向的内容返回来,并且按(1)的要求认为数据是 unsigned char(3) 这个函数还调整指针 pStack+,按(1)的要求跳过一个 unsigned char 类型的数据单元这个函数自然也可以这样用 va_arg ( pStack , unsigned int ) ,您能明白意思吧?一切的工作都做完了以后,我们要释放 pSta

8、ck 指针,也就是利用函数 va_end( pStack ) ;这一步的意义我还没发现。算是按要求来吧。最后把全部代码给大家看看:#include#includeunsigned char max( unsigned char n ,.) unsigned char max = 0 , temp ;va_list pStack;va_start( pStack , n );while( n- ) /注意这里是 n 减减temp = va_arg( pStack , unsigned char ) ;max = ( max temp ? max : temp ) ;va_end( pStack

9、) ;return max ;void main( void )unsigned char M ;M = max( 5 , 20 , 45 , 55 , 80 , 95 );while(1);好了,您调试一下吧。应该可以看到结果了。从这个例子中您会发现,必须要有办法知道倒底有几个参数被传递过来了。这也就是 unsigned char max( unsigned char n ,.)中 n 的意义,一个参数也没有的函数 unsigned char max( . )C 语言是不被允许的。注意:unsigned char max( void )有一个参数。另外,我们这里也根本没涉及到_cdecl 和_stdcall 的问题,程序很好地运行着,但是这不代表知道这些毫无意义。它也许在您今后的学习中会有所帮助。更进一步:您现在是不是对实做单片机的 printf 充满了热情呢?其实,能识别%i,%c,%s 的控制打印函数,在单片机的应用中是很好的,我们让%i 表示 unsigned int 用%c 表示 unsigned char 用%s 表示字符串。这个函数您自己实做吧,因为这涉及到您习惯的单片机、波特率、串口调试软件我自己做了一个 printf 如果大家需要可以加我 QQ924465550

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。