设为首页 加入收藏

TOP

建议15:尽量不要使用可变参数(1)
2013-10-07 14:47:22 来源: 作者: 【 】 浏览:46
Tags:建议 尽量 不要 使用 可变 参数

建议15:尽量不要使用可变参数(1)

在某些情况下我们希望函数参数的个数可以根据实际需要来确定,所以C语言中就提供了一种长度不确定的参数,形如:“...”,C++(www.cppentry.com)语言也继承了这一语言特性。在采用ANSI标准形式时,参数个数可变的函数的原型是:

  1. type funcname(type para1, type para2, ...); 

这种形式至少需要一个普通的形式参数,后面的省略号(...)不能省去,它是函数原型必不可少的一部分。典型的例子有大家熟悉的printf()、scanf()函数,如下所示的就是printf()的原型:
  1. int printf( const char *format ,  ... ); 

除了参数format固定以外,其他参数的个数和类型是不确定的。在实际调用时可以有以下形式:
  1. int year = 2011;  
  2. char str[] = "Hello 2011";  
  3. printf("This year is %d", year);  
  4. printf("The greeting words are %s", str);  
  5. printf("This year is %d ,and the greeting words are:%s", year, str); 

也许这些已经为大家所熟知,但是可变参数的实现原理却是C语言中比较难理解的一部分。在标准C语言中定义了一个头文件,专门用来对付可变参数列表,其中,包含了一个va_list的typedef声明和一组宏定义va_start、va_arg、va_end,如下所示:

  1. // File: VC++(www.cppentry.com)2010中的stdarg.h  
  2. #include <vadefs.h> 
  3.  
  4. #define va_start _crt_va_start  
  5. #define va_arg _crt_va_arg  
  6. #define va_end _crt_va_end  
  7.  
  8.  
  9. // File: VC++(www.cppentry.com)2010中的vadefs.h  
  10. #ifndef _VA_LIST_DEFINED  
  11. typedef char *  va_list;  
  12. #define _VA_LIST_DEFINED  
  13. #endif  
  14.  
  15. #ifdef  __cplusplus  
  16. #define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )  
  17. #else  
  18. #define _ADDRESSOF(v)   ( &(v) )  
  19. #endif  
  20.  
  21. #ifdefined(_M_IX86)  
  22. #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )  
  23. #define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )  
  24. #define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )  
  25. #define _crt_va_end(ap)      ( ap = (va_list)0 ) 

定义_INTSIZEOF(n)是为了使系统内存对齐;va_start(ap, v)使ap指向第一个可变参数在堆栈中的地址,va_arg(ap,t)使ap指向下一个可变参数的堆栈地址,并用*取得该地址的内容;最后变参获取完毕,通过va_end(ap)让ap不再指向堆栈,如图1-3所示。
 
图1-3 可变参数存储示意图

由于将va_start、va_arg、va_end定义成了宏,可变参数的类型和个数在该函数中完全由程序代码控制,并不能智能地进行识别,所以导致编译器对可变参数的函数原型检查不够严格,难于查错,不利于写出高质量的代码。

参数个数可变具有很多的优点,为程序员带来了很多的方便,但是上面C风格的可变参数却存在着如下的缺点:

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇建议15:尽量不要使用可变参数(2.. 下一篇建议16:慎用goto

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: