控制工程师论坛

教程与手册

C/C++语言可变参数表深层探索

xilinxue
xilinxue

2008-11-10


1.引言

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++支持可变参数表的深层机理进行探索。
2.可变参数表的用法
2.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]
对这个宏的具体含义我们将在第3 节深入讨论。
而va_end 宏被用来结束可变参数的获取,其定义为:
#define va_end ( list )
可以看出,va_end ( list )实际上被定义为空,没有任何真实对应的代码,用于代码对称,与va_start
对应;另外,它还可能发挥代码的“自注释”作用。所谓代码的“自注释”,指的是代码能自己注释
自己。
下面我们以具体的例子来说明以上三个宏的使用方法。

回帖

评论3

总共 , 当前 /
首页 | 登录 | 注册 | 返回顶部↑
手机版 | 电脑版
版权所有 Copyright(C) 2016 CE China