printf函数的实现原理.docVIP

  1. 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
printf函数的实现原理

Printf函数实现原理 要了解变参函数的实现,首先我们的弄清楚几个问题: 1:该函数有几个参数。 2:该函数增样去访问这些参数。 3:在访问完成后,如何从堆栈中释放这些参数。 对于c语言,它的调用规则遵循_cdedl调用规则。 在_cdedl规则中:1.参数从右到左依次入栈 ??????????????? 2.调用者负责清理堆栈 ??????????????? 3.参数的数量类型不会导致编译阶段的错误 要弄清楚变参函数的原理,我们需要解决上述的3个问题,其中的第三个问题,根据调 用原则,那我们现在可以不管。 要处理变参函数,需要用到 va_list 类型,和 va_start,va_end,va_arg 宏定义。我 看网上的许多资料说这些参数都是定义在stdarg.h这个头文件中,但是在我的linux机 器上,我的版本是fedorea 14,用vim访问的时候,确是在 acenv.h这个头文件中,估 计是内核的版本不一样的原因吧!!! 上面的这几个宏和其中的类型,在内核中是这样来实现的: #ifndef _VALIST #define _VALIST typedef char *va_list; #endif??????????????? /* _VALIST */ /* * Storage alignment properties */ #define? _AUPBND??????????????? (sizeof (acpi_native_int) - 1) #define? _ADNBND??????????????? (sizeof (acpi_native_int) - 1) /* * Variable argument list macro definitions */ #define _bnd(X, bnd)??????????? (((sizeof (X)) + (bnd)) (~(bnd))) #define va_arg(ap, T)?????????? (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) #define va_end(ap)????????????? (void) 0 #define va_start(ap, A)???????? (void) ((ap) = (((char *) (A)) + (_bnd (A,_AUPBND)))) #endif??????????????? /* va_arg */ 首先来看 va_list 类型,其实这是一个字符指针。 va_start,是使ap指针指向变参函数中的下一个参数。 我们现在来看_bnd 宏的实现: 首先: typedef s32 acpi_native_int; typedef int??????????? s32; 看出来,acpi_native_int 其实就是 int 类型,那么, #define? _AUPBND??????????????? (sizeof (acpi_native_int) - 1) #define? _ADNBND??????????????? (sizeof (acpi_native_int) - 1) 这两个值就应该是相等的,都-等于:3==0按位取反后的结果就是:0xfffff ffc,因此, _bnd(x,bnd)宏在32位机下就是 (((sizeof (X)) + (3)) (0xfffffffc)),那么作用就很明显是取4的整数,就相当与 整数除法后取ceiling--向上取整。 回过头来看 va_start(ap,A),初始化参数指针ap,将函数参数A右边右边第一个参数地 址赋值给ap,A必须是一个参数的指针,所以,此种类型函数至少要有一个普通的参数 ,从而提供给va_start ,这样va_start才能找到可变参数在栈上的位置。 va_arg(ap,T),获得ap指向参数的值,同时使ap指向下一个参数,T用来指名当前参数类 型。 va_end 在有些简单的实现中不起任何作用,在有些实现中可能会把ap改成无效值,这 里,是把ap指针指向了 NULL。 c标准要求在同一个函数中va_start 和va_end 要配对的出现。 那么到现在,处理多参数函数的步骤就是 1:首先是要保证该函数至少有一个参数,同时用...参数申明函数是变参函数。 2:在函数内部以va_start(ap,A)宏初始化参数指针。 3:用va_arg(ap,T)从左到右逐个取参数值。 p

文档评论(0)

xcs88858 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

版权声明书
用户编号:8130065136000003

1亿VIP精品文档

相关文档