对C/C 可变参数表的深层探索
2008-02-23 05:24:04来源:互联网 阅读 ()
C/C 语言有一个不同于其他语言的特性,即其支持可变参数,典型的函数如printf、scanf等能够接受数量不定的参数。如:
printf ( "I love you" ); printf ( "%d", a ); printf ( "%d,%d", a, b ); |
第一、二、三个printf分别接受1、2、3个参数,让我们看看printf函数的原型:
int printf ( const char *format, ... ); |
从函数原型能够看出,其除了接收一个固定的参数format以外,后面的参数用"…"表示。在C/C 语言中,"…"表示能够接受不定数量的参数,理论上来讲,能够是0或0以上的n个参数。
本文将对C/C 可变参数表的使用方法及C/C 支持可变参数表的深层机理进行探索。
可变参数表的用法
1、相关宏
标准C/C 包含头文档stdarg.h,该头文档中定义了如下三个宏:
void va_start ( va_list arg_ptr, prev_param ); /* ANSI version */ type va_arg ( va_list arg_ptr, type ); void va_end ( va_list arg_ptr ); |
在这些宏中,va就是variable argument(可变参数)的意思;arg_ptr是指向可变参数表的指针;prev_param则指可变参数表的前一个固定参数;type为可变参数的类型。va_list也是个宏,其定义为typedef char * va_list,实质上是一char型指针。char型指针的特点是 、--操作对其作用的结果是增1和减1(因为sizeof(char)为1),和之不同的是int等其他类型指针的 、--操作对其作用的结果是增sizeof(type)或减sizeof(type),而且sizeof(type)大于1。
通过va_start宏我们能够取得可变参数表的首指针,这个宏的定义为:
#define va_start ( ap, v ) ( ap = (va_list)&v _INTSIZEOF(v) ) |
显而易见,其含义为将最后那个固定参数的地址加上可变参数对其的偏移后赋值给ap,这样ap就是可变参数表的首地址。其中的_INTSIZEOF宏定义为:
#define _INTSIZEOF(n) ((sizeof ( n ) sizeof ( int ) - 1 ) & ~( sizeof( int ) - 1 ) ) |
va_arg宏的意思则指取出当前arg_ptr所指的可变参数并将ap指针指向下一可变参数,其原型为:
#define va_arg(list, mode) ((mode *)(list =\ (char *) ((((int)list (__builtin_alignof(mode)<=4?3:7)) &\ (__builtin_alignof(mode)<=4?-4:-8)) sizeof(mode))))[-1] |
对这个宏的具体含义我们将在后面深入讨论。
而va_end宏被用来结束可变参数的获取,其定义为:
#define va_end ( list ) |
能够看出,va_end ( list )实际上被定义为空,没有任何真实对应的代码,用于代码对称,和va_start对应;另外,他还可能发挥代码的"自注释"作用。所谓代码的"自注释",指的是代码能自己注释自己。
下面我们以具体的例子来说明以上三个宏的使用方法。
2、一个简单的例子
#include <stdarg.h> /* 函数名:max * 功能:返回n个整数中的最大值 * 参数:num:整数的个数 ...:num个输入的整数 * 返回值:求得的最大整数 */ int max ( int num, ... ) { int m = -0x7FFFFFFF; /* 32系统中最小的整数 */ va_list ap; va_start ( ap, num ); for ( int i= 0; i< num; i ) { int t = va_arg (ap, int); if ( t > m ) { m = t; } } va_end (ap); return m; } /* 主函数调用max */ int main ( int argc, char* argv[] ) { int n = max ( 5, 5, 6 ,3 ,8 ,5); /* 求5个整数中的最大值 */ cout << n; return 0; } |
函数max中首先定义了可变参数表指针ap,而后通过va_start ( ap, num )取得了参数表首地址(赋给了ap),其后的for循环则用来遍历可变参数表。这种遍历方式和我们在数据结构教材中经常看到的遍历方式是类似的。
函数max看起来简洁明了,但是实际上printf的实现却远比这复杂。max函数之所以看起来简单,是因为:
(1) max函数可变参数表的长度是已知的,通过num参数传入;
(2) max函数可变参数表中参数的类型是已知的,都为int型。
而printf函数则没有这么幸运。首先,printf函数可变参数的个数不能轻易的得到,而可变参数的类型也不是固定的,需由格式字符串进行识别(由%f、%d、%s等确定),因此则涉及到可变参数表的更复杂应用。
下面我们以实例来分析可变参数表的高级应用。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇: C/C 编程新手错误语录
下一篇: C 箴言:确保公开继承模拟“is-a”
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash