C语言 变参 stdarg

一个函数可以用不同类型的不同数量的参数来调用。包含文件stdarg.h声明一个类型va_list,并定义了三个宏,用于逐步遍历被调用函数不知道其数量和类型的参数列表。在使用过程中需要包含头文件stdarg.h:
#include <stdarg.h>

void va_start(va_list ap, last);
#define va_start(list,param1) // ( list = (va_list)&param1+ sizeof(param1) )
a)va_start()宏初始化ap,以便va_arg()和va_end()后续使用,必须首先调用该宏。
b)last是变量参数列表前最后一个参数的名称,也就是调用函数的最后一个可知的参数的类型。

type va_arg(va_list ap, type);
#define va_arg(list,mode) //( (mode *) ( list += sizeof(mode) ) )[-1]
a)参数ap是由va_start()初始化的va_list ap。每次调用va_arg()都会修改ap,以便下一次调用返回下一个参数。参数类型是指定的类型名称,这样就可以通过在类型中添加来获得指向具有指定类型的对象的指针的类型。
b)va_arg()宏在va_start()宏之后的第一次使用将返回在last之后的参数。连续的调用返回其余参数的值。
c)如果没有下一个参数,或者类型与实际的下一个参数的类型不兼容,将会发生随机错误。

void va_end(va_list ap);
#define va_end(list) //( list = (va_list)0 )
每次对va_start()的调用都必须与同一个函数中对应的va_end()调用相匹配。在调用va_end(ap)之后,变量ap是未定义的。可以对列表进行多次遍历,每个遍历都由va_start()和va_end()括起来

void va_copy(va_list dest, va_list src);
实现一个列表的拷贝。不常用。

一个简单的相同类型不同数量的参数:

#include <stdarg.h>
#include <stdio.h>


int test(int num, ...);

int main(void)
{
        int num = 5;
        printf("%d\n", test(num, 1,2,3,4,5));

        return 0;
}

int test(int num, ...)
{
        int arg_count = 0;
        va_list ap = NULL;	// 使用之前必须,定义一个va_list的变量
        va_start(ap, num);	// 该函数小时ap指向num后面的第一个参数的地址
        for(; arg_count < num; arg_count++){
                printf("%d-%d\n", arg_count,va_arg(ap, int));	
                /*va_arg(ap, int)返回一个int类型的值,传参的类型是什么,
                va_arg的第二个参数就填什么,我这里传的int类型所以va_arg这传的是int*/ 
        }
        va_end(ap); // 清空ap
        return arg_count;
}

运行结果

0-1
1-2
2-3
3-4
4-5
5

个人总结的使用步骤:
1)va_start使用之前必须先定义va_list类型的变量,该变量是一个指针。
va_list p;
2)va_start使用是将va_list类型的p进行初始化,并且获取变参的地址。
3)每一次调用va_arg,都将获取到一个传入va_arg所对应数据类型的参数,如果传入的数据类型跟参数的类型不同,会发生一个随机的错误。va_list类型的p,会调过这个参数的地址,并指向下一个参数的地址,以便下次调用va_arg时返回相对应的值。当参数已经取完了,再调用va_arg时,也会出现一个随机的错误。
4)va_end 是与va_start成对出现的,在使用完之后,一定要调用va_end。(具体不知道什么原因,好像是清空va_list类型p,谁知道的话,可以留言互相学习一下)。
5)如果再次操作2-4步骤的话,会得到与2-4步骤相同的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值