stdarg宏用法--------可变参数调用

stdarg宏------可变参数调用,定义于stdarg.h头文件,是标准库的一部分,这个主要在一些内核代码中经常看到,这个头文件声明了类型va_list和三个宏-----va_start,va_arg,va_end。一般声明一个va_list的变量,与这几个宏配合使用,访问参数的值。
var_arg用来访问参数列表的未确定部分,这个变量通过调用va_start来初始化。
va_start函数的第一个参数是va_list变量的名字,第二个参数是省略号前最后一个有名字的参数。初始化过程把var_arg变量设置为指向可变参数部分的第一个参数。
va_arg,这个宏接受两个参数:va_list变量和参数列表中下一个参数类型。va_arg返回这个参数的值,并使var_arg指向下一个可变参数。

在访问完最后一个可变参数之后,需要调用va_end。

函数在堆栈中的分布情况是:地址从高到低,依次是函数参数列表,函数返回地址,函数执行代码
堆栈中哦,各个函数的分布情况是倒序的
参数在堆栈中的分布情况如下:
最后一个参数
倒数第二个参数

第一个参数
函数返回地址
函数代码段

#include<stdarg.h>
#include<stdio.h>
void simple_va_fun(int a,...)
{
	va_list arg_ptr;
	va_start(arg_ptr,a);		    //第一个可选参数地址
	for(int i=0;i<a;i++)
	{
		int k=va_arg(arg_ptr,int);		//VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
		printf("%d\n",k);
	}
	va_end(arg_ptr);			//将指针置为无效
	return;
}
int main()
{
	simple_va_fun(2,20,30);
	printf("\n");
	simple_va_fun(3,20,30,40);
	return 0;
}

运行结果如下:

20
30

20
30
40

再对比下面的这个代码

#include<stdarg.h>
#include<stdio.h>
void simple_va_fun(int b,int a,...)				//区别,多了一个参数
{
	va_list arg_ptr;
	va_start(arg_ptr,a);		    //第一个可选参数地址
	for(int i=0;i<a;i++)
	{
		int k=va_arg(arg_ptr,int);		//VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
		printf("%d\n",k);
	}
	va_end(arg_ptr);			//将指针置为无效
	return;
}
int main()
{
	simple_va_fun(3,2,20,30);       //这里相应的多了一个参数
	printf("\n");
	simple_va_fun(4,3,20,30,40);
	return 0;
}

再看运行结果:

20
30

20
30
40

也就是说va_start的第二个参数只对省略号前最后一个有名字的参数有效,与前面有名字的参数并无关系。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在C语言中,我们可以使用可变参数来处理不同数量的参数。以下是一些常见的可变参数: 1. va_start:该用于初始化一个指向可变参数的指针,以便在函数中访问可变参数。 2. va_arg:该用于获取可变参数列表中的下一个参数,它需要两个参数:一个是类型,另一个是可变参数的指针。 3. va_end:该用于结束可变参数列表的访问。 下面是一个使用可变参数的示例: ```c #include <stdarg.h> #include <stdio.h> void print_args(int num, ...) { va_list args; va_start(args, num); for (int i = 0; i < num; i++) { int arg = va_arg(args, int); printf("%d ", arg); } va_end(args); } int main() { print_args(3, 1, 2, 3); return 0; } ``` 在上面的示例中,我们定义了一个名为`print_args`的函数,它采用一个整数参数`num`,后跟可变数量的整数参数。在函数中,我们需要使用`va_list`类型的变量来存储可变参数列表。我们使用`va_start`来初始化`args`变量,并使用`va_arg`在循环中获取每个参数的值。最后,我们使用`va_end`来结束可变参数列表的访问。 此外,还有一些其他的可变参数,例如`va_copy`,用于复制可变参数列表;`va_list`,用于声明可变参数列表等。 ### 回答2: 操作可变参数有以下几种: 1. 使用__VA_ARGS__: 这是最常用的方法之一。通过在定义中使用__VA_ARGS__,可以将调用中的参数直接传递给展开部分。 2. 使用可变参数列表: 可以使用定义中的“...”来表示可变参数,并使用va_list和va_start等来操作可变参数列表。 操作流程如下: 1. 定义一个并使用可变参数列表: 首先需要定义一个,并在定义中使用“...”来表示可变参数。在展开部分,可以使用va_list, va_start,va_arg来操作可变参数列表。 2. 初始化可变参数列表: 使用va_start来初始化可变参数列表,并将最后一个固定参数的地址作为参数传入。 3. 读取可变参数: 使用va_arg可以按照指定的类型来读取可变参数。 4. 释放可变参数列表: 在操作完成后,需要使用va_end来释放可变参数列表。 5. 进行其他操作: 根据需要,可以在展开部分进行其他操作,例如将可变参数传递给其他函数进行处理。 总结: 操作可变参数可以使用__VA_ARGS__或者使用可变参数列表来实现。使用可变参数列表时,需要使用va_list, va_start,va_arg和va_end等来操作可变参数列表。在使用完成后,需要释放可变参数列表。操作可变参数可以用于实现各种功能,例如打印日志、参数传递等。 ### 回答3: 操作可变参数包括va_start、va_arg、va_end和va_copy。 操作可变参数的操作流程如下: 1. 使用va_start开始可变参数的处理。这个接受两个参数,第一个是类型为va_list的变量名,第二个是最后一个固定参数的变量名。 2. 使用va_arg获取接下来的可变参数的值。这个接受两个参数,第一个是类型为va_list的变量名,第二个是要获取的参数的类型。 3. 使用va_end结束对可变参数的处理。这个接受一个参数,即类型为va_list的变量名。 4. 如果需要在处理可变参数前后进行多次处理,可以使用va_copy进行参数复制。这个接受两个参数,第一个是类型为va_list的变量名,第二个是要复制的原始变量。 使用可变参数可以在编写函数时处理不定个数的参数。通过使用上述,可以逐个获取可变参数的值,进行相应的处理。其中,va_start用于确定可变参数的起始位置,va_arg用于获取可变参数的值,va_end用于结束对可变参数的处理,而va_copy用于参数复制。 举例来说,当需要编写一个求和函数,可以使用可变参数来处理不同数量的参数: ``` #include <stdio.h> #include <stdarg.h> int sum(int count, ...) { va_list args; va_start(args, count); int result = 0; for (int i = 0; i < count; i++) { int num = va_arg(args, int); result += num; } va_end(args); return result; } int main() { int result1 = sum(3, 1, 2, 3); int result2 = sum(5, 1, 2, 3, 4, 5); printf("Result 1: %d\n", result1); printf("Result 2: %d\n", result2); return 0; } ``` 上述代码中,通过sum函数可以传入不同数量的参数,并计算它们的和。可变参数在sum函数中使用,通过遍历每个参数,获取其值,并累加到result变量中,最后返回总和。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值