C可变参数详解及其函数设计

在stdarg.h文件中有如下几个宏定义:

#include <vadefs.h>

#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end

#endif  /* _INC_STDARG */


 其定义在vadefs.h中分别为:

#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址 

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址 

#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效


 

在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自己插入的代码段的目的.

总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.

堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:

     

       最后一个参数


  倒数第二个参数


  ...


  第一个参数


  函数返回地址


  函数代码段


代码示例:这里是一个可变参数的加法函数

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

/*功能:可变参数求和
 *参数:numCount参数个数 ...可变求和参数
 *返回值:参数相加的和
 */
int sum(int numCount,...)
{
	int result = 0;     //计算结果
	va_list ap;         //初始化指向可变参数列表的指针(typedef char* va_list)

	va_start(ap,numCount);          //将第一个可变参数的地址付给ap,即ap指向可变参数列表的开始
	for(int i = 0;i<numCount;i++)
		result += va_arg(ap,int);	//得到第一个可变参数的值,并且ap指针上移一个_INTSIZEOF(int),即指向下一个可变参数的地址. 
	va_end(ap);                     //置空ap,即ap=(void *)0; 

	return result;
}

int main(void)
{
	printf("20+15+3+8=%d\n",sum(4,20,15,3,8));

	system("pause");
	return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值