您的位置:首页 > 其它

浅析可变参数列表

2016-04-18 16:55 204 查看
可不参数列表可以让函数在不同时候接受不同数目的参数。

C语言可变参数列表使用总可分为4个部分.

1、va_list

首先,我们先来看一下它的定义:

#ifdef _M_ALPHA

typedef struct{

char*a0;/*pointertofirsthomedintegerargument*/

intoffset;/*byteoffsetofnextparameter*/

}va_list;

#else

typedef char*va_list;#endif

就我们所知,typedef将va_list定义成了一个char*类型;

所以在使用va_list时,

va_list arg;//作用就是将arg定义成了一个char类型的指针

2、va_start

va_start是一个宏,它的作用是获取第一个参数的地址,即括号内的最左边第一个参数

的地址。

它的定义为:

#defineva_start(ap,v)(ap=(va_list)&v+_INTSIZEOF(v))

使ap指向第一个参数的地址。(ap即为va_list所定义的指针)

这里使用到了一个_INTSIZEOF,注意,它也是一个宏,作用是获取目标参数v所占用空间的

长度大小。

它在这里起到了一个初始化的作用。具体的使用在下面会举例。

3、va_arg

va_arg是一个宏,它的作用是向后访问。定义为:

#defineva_arg(ap,t)(*(t*)((ap+=_INTSIZEOF(t))-_INTSIZEOF(t)))

每次调用,它先获取当前的参数,并使指针ap指向下一个参数。

(至于这里为什么先使ap加上一个_INTSIZEOF(t), 又减去一个_INTSIZEOF(t)。从而起到是ap

指针向后移动的作用,博主尚未弄明白)。

4、va_end

类型也是宏,作用为清空 va_list所定义的可变参数列表。

#define  va_end(ap)  (ap=(va_list)0)

5、可变参数列表有几个限制条件

<1> 函数的参数至少含有一个。

<2> va_start无法计算参数的个数。

<3> 无法直接知道参数类型。

<4> va_arg如果给定了错误的类型,结果不可预料。

下面来看一个例子

// 利用可变参数列表模拟printf函数输出字符串,字符。
#include<stdio.h>
#include<stdarg.h>
void print(const char *format,...)
{
va_list arg;
//定义arg(char类型)指针
va_start(arg,format);
//对arg进行初始化,使其指向第一个参数
while(*format)
{
switch(*format)
//因为有字符,字符串两种情况,所以这里用switch比较好。
{

case's':
//若读取到为s,则为字符串
{
char *str=va_arg(arg,char*);
/*注意,这里要用一个局部变量对va_arg(arg,char*)进行一次保存,
因为每次调用一次va_arg(arg,char*),它都会向后移动, 若,直接
puts(va_arg(arg,char*))会输出下一个参数的值。*/
puts(str);
}
break;
case'c':
//若为猜,则为字符。
{
char tmp=va_arg(arg,char);//若此处char不行,换用int 试一下。博主遇到过这种情况,尚未明白。
//同样用tmp进行一次保存。
/*注意,va_arg不会辨别参数的类型,该参数是什么类型,va_arg括号中
第二个位置就写什么类型,不要写错,不热会造成不可预料的后果。这也是
可变参数列表的一个限制条件。*/
putchar(tmp);
}
break;

default:
/*当switch所有情况列举完后,用default分支结尾。即使真的不需要default,
也应该保留语句 ,具体作用自己网查*/
putchar(*format);
break;
}
format++;
}
va_end(arg);//最后清空va_list定义的arg

}
int main()
{
print("s ccc.\n","hello",'b','i','t');
return 0;
}


执行后结果应为:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: