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

开发 后端
C++ Sum函数是C++语言程序的主要组成部分,一个函数可以调用其他函数,在设计良好的程序中,每个函数都有特定的目的。

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

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

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

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

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

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

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

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

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

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

【编辑推荐】

  1. C与C++中标准输入实现方式上的一点区别
  2. C++编译器如何对Const常量进行分配存储空间
  3. C++类库设计的基本构思与方法
  4. 玩转C++语言的几种方法
  5. 如何更好的进行C++代码编制
责任编辑:chenqingxiang 来源: 计世网
相关推荐

2022-07-18 15:32:37

C++虚函数表

2010-02-06 16:39:45

C++ assert(

2010-01-14 17:42:47

CC++

2010-01-28 16:31:54

C++类型

2010-01-20 17:32:16

C++函数

2010-01-25 10:10:42

C++函数参数

2023-11-17 14:10:08

C++函数

2010-01-25 09:57:39

C++函数参数

2010-02-06 16:05:51

C++ Vector

2010-02-04 10:19:39

C++多线程

2010-01-15 10:32:21

C++语言

2010-01-26 14:46:42

C++语言

2010-02-03 10:05:48

C++ enum枚举

2010-01-27 17:16:52

C++构造函数

2010-01-13 10:16:42

C++软件

2010-02-05 17:09:19

C++创建Web服务

2010-01-26 17:16:33

C++应用程序

2010-01-28 14:54:01

C++资源管理

2022-09-12 06:35:00

C++协程协程状态

2010-01-27 15:50:23

C++复杂性
点赞
收藏

51CTO技术栈公众号