函数参数是以数据结构:栈的形式存取,从右至左入栈。
首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。
栈底 高地址
| .......
| 函数返回地址
| .......
| 函数最后一个参数
| ....
| 函数第一个可变参数 <--va_start后ap指向
| 函数最后一个固定的参数:ap根据其地址计算出
| ....
| 函数第一个固定的参数
栈顶 低地址
定义可变参数函数:
一、最少需要定义一个固定参数:它是最后一个入栈的参数
二、使用stdarg.h头文件
1、一个字符型指针变量的定义:va_list
typedef char * va_list;//va_list就相当于 char *
作用:定义保存函数传入的第一个参数的指针
(1)va_start(ap,v):用来获取可变参数列表中的第一个参数的存储地址,接受两个参数:va_list变量名和省略号前最后一个有名字的参数
(2)va_arg(ap,type):用来访问可变参数值,接受两个参数:va_list变量和参数列表中下一个参数的类型
(3)va_end(ap):用来结束va_start()的调用
例:
首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。
栈底 高地址
| .......
| 函数返回地址
| .......
| 函数最后一个参数
| ....
| 函数第一个可变参数 <--va_start后ap指向
| 函数最后一个固定的参数:ap根据其地址计算出
| ....
| 函数第一个固定的参数
栈顶 低地址
定义可变参数函数:
一、最少需要定义一个固定参数:它是最后一个入栈的参数
二、使用stdarg.h头文件
1、一个字符型指针变量的定义:va_list
typedef char * va_list;//va_list就相当于 char *
作用:定义保存函数传入的第一个参数的指针
va_list temp;//temp是定义来指向第一个可变参数的指针
2、三个宏的定义:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )//实现int的倍数对其
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )//根据最后一个入栈的已知参数v来计算出第一个可变参数的存储地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
理解:(1)va_start(ap,v):用来获取可变参数列表中的第一个参数的存储地址,接受两个参数:va_list变量名和省略号前最后一个有名字的参数
(2)va_arg(ap,type):用来访问可变参数值,接受两个参数:va_list变量和参数列表中下一个参数的类型
(3)va_end(ap):用来结束va_start()的调用
例:
#include <stdio.h>
#include <stdarg.h>
int fun1(int arv_num,int arv1, ...)//arv_num是可变参数的数量
{
va_list va_pr;
int sum,count;
sum = arv1;
va_start(va_pr,arv1);
for(count=0;count<arv_num;count++)
{
sum = va_arg(va_pr,int)+sum;
}
va_end(va_pr);
return sum;
}
int main()
{
printf("The sum is %d\n", fun1(2, 20,30,10)); //
return 0;
}