C语言 va_list获取参数列表原理

问题引入:我们知道,C语言给我们提供了一个不确定参数个数传参的方法,这个方法就是在传参列表后面加上一个...。具体形式如下: 

#include <stdio.h>

void print(int a,...)
{

}

其中获取参数列表的方法如下:

#include <iostream>
#include <cstdarg>
using namespace std;

void print(int begin, ...)   //可变参数列表需要指定一个传入参数begin来获取其他传入参数的地址
{
	va_list v;
	
	va_start(v,begin);

	int record = begin;

	while (1)
	{
		cout << record;
		record = va_arg(v, int);
		if (record == 0)
			break;
	}

	va_end(v);
}
int main()
{
	int a = 10;         //这里定义a这个变量只是用于方便观看调用print函数后,压栈后的内存变化
	print(1,2,3,4,5,6,7,0);    //这里的0是结束的标记
	return 0;
}

原理如下:C语言在调用函数时,会把函数参数压栈,而且函数参数在内存上的排列是连续的。通过VS强大的调试器我们可以轻松观测到内存的变化,在调用print函数后,内存的变化如下:

可以看到上图变红的部分就是在调用print函数压栈后的内存变化。分别是0x00000001,0x00000002,....0x00000007,0x00000000。他们是连续的。我们在看变量v的地址和值:

可以看到变量v的值是0x00cff60c,我们顺着上面图中的内存指示可以看到,0x00cff60c正好是上面图中压栈后值2(0x00000002)的地址(这是在执行va_start(v,begin)之后v指示的值)。讲到这里,大家应该大概明白了va_list获取参数列表的原理。其实就是v指向了压栈后的那块内存的首地址,然后我们通过va_arg(v,int)得到v指向的那块地址的值(即0x00000002=2),并将v指向的内存往后偏移4个字节从而指向后面的参数的地址,这里的int只是提供了一个偏移量,好让v正确的指向下一个参数的地址,当然int也可以是double,char或者任意长度(前提是你知道你想要获取的是什么)。 当v指向我们指定的末尾值(在这里是0)的地址时,就意味着我们已经读取了所有传入的参数。

可能有讲得不对的地方,欢迎大家批评指正。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值