剖析C++Sum函数获取参数

在C++中的函数当中,C++ Sum函数可以使用SUM来进行任何求和,但无法使用任何名称访问其他的几个不定参数,但此时由于栈上其他的几个参数实际恰好依序排列在参数SUM的高地址方向。

企业建站必须是能够以充分展现企业形象为主要目的,是企业文化与产品对外扩展宣传的重要窗口,一个合格的网站不仅仅能为公司带来巨大的互联网上的收集和信息发布平台,创新互联公司面向各种领域:铜雕雕塑网站设计营销型网站建设解决方案、网站设计等建站排名服务。


因此可以很简单地通过num的地址计算出其他参数的地址。sum函数的实现如下:

 
 
 
  1. int sum(unsigned num, ...)
  2.   {
  3.   int* p = &num + 1;
  4.   int ret = 0;
  5.   while (num--)
  6.   ret += *p++;
  7.   return ret;
  8.   }

在这里我们可以观察到两个事实:

(1)C++ Sum函数获取参数的量仅取决于num参数的值,因此,如果num参数的值不等于实际传递的不定参数的数量,那么C++ Sum函数可能取到错误的或不足的参数。

(2)cdecl调用惯例保证了参数的正确清除。我们知道有些调用惯例(如stdcall)是由被调用方负责清除堆栈的参数,然而,被调用方在这里其实根本不知道有多少参数被传递进来,所以没有办法清除堆栈。而cdecl恰好是调用方负责清除堆栈,因此没有这个问题。

printf的不定参数比sum要复杂得多,因为printf的参数不仅数量不定,而且类型也不定。所以printf需要在格式字符串中注明参数的类型,例如用%d表明是一个整数。printf里的格式字符串如果将类型描述错误,因为不同参数的大小不同,不仅可能导致这个参数的输出错误,还有可能导致其后的一系列参数错误。

 
 
 
  1.  #define va_list char*
  2.   #define va_start(ap,arg) (ap=(va_list)&arg+sizeof(arg))
  3.   #define va_arg(ap,t) (*(t*)((ap+=sizeof(t))-sizeof(t)))
  4.   #define va_end(ap) (ap=(va_list)0)
  5. printf的狂乱输出
  6.   #include
  7.   int main()
  8.   {
  9.   printf("%lf\t%d\t%c\n", 1, 666, 'a');
  10.   }

在这个程序里,printf的第一个输出参数是一个int(4字节),而我们告诉printf它是一个double(8字节以上),因此C++ Sum函数的输出会错误,由于printf在读取double的时候实际造成了越界,因此后面几个参数的输出也会失败。

在很多时候我们希望在定义宏的时候也能够像print一样可以使用变长参数,即宏的参数可以是任意个,这个功能可以由编译器的变长参数宏实现。在GCC编译器下,变长参数宏可以使用“##”宏字符串连接操作实现。

本文标题:剖析C++Sum函数获取参数
文章链接:http://www.csdahua.cn/qtweb/news19/481019.html

网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网