参数列表_用户5673143920_新浪博客

固定参数列表函数,
void fixed_args_func(int a, double b, char *c)
{
printf("a = 0x%p\n", &a);  // &a得到a的地址,a是int类;
printf("b = 0x%p\n", &b);  // &b得到b的地址,b是double类;
printf("c = 0x%p\n", &c);  // &c得到c的地址,c是char*类;
}

可变参数函数  
va_list是用于存放参数列表的数据结构。
va_start函数根据初始化last来初始化参数列表。
va_arg函数用于从参数列表中取出一个参数,参数类型由type指定。
va_copy函数用于复制参数列表。
va_end函数执行清理参数列表的工作。

上述函数通常用宏来实现,例如标准ANSI形式下,这些宏的定义是:
typedef char * va_list; //字符串指针
#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 )
使用宏_INTSIZEOF是为了按照整数字节对齐指针,因为c调用协议下面,参数入栈都是整数字节(指针或者值)

va_start(ap, fmt);用于根据fmt初始化可变参数列表。
va_arg(ap, char *);用于从参数列表中取出一个参数,其中的char *用于指定所取的参数的类型为字符串。每次调用va_arg后,参数列表ap都会被更改,以使得下次调用时能得到下一个参数。
va_end(ap);用于对参数列表进行一些清理工作。调用完va_end后,ap便不再有效。
实现printf函数:通过调用va_start函数,得到参数列表一个个取出参数输出即可。
求和:
int sum(int cnt,...)
{
int sum=0;
int i;
va_list ap;
va_start(ap,cnt);
for(i=0;i
sum+=va_arg(ap,int);
va_end(ap);
return sum;
}

变长参数的函数
void var_args_func(const char * fmt, ... )
{
... ...
}
1.至少一个最左固定参数得到其中固定参数的地址,但是依然无法从声明中得到其他变长参数的地址
2.无论"..."中有多少个参数、每个参数是什么类型的,它们都和固定参数的传参过程是一样的
3.栈操作知道某函数帧的栈上的一个固定参数的位置,推导出其他变长参数的位置
int main()
{
fixed_args_func(17, 5.40, "hello world");
return 0;
}
a = 0x0022FF50
b = 0x0022FF54
c = 0x0022FF5C
4.参数是从右到左,逐一压入栈中的
(栈的延伸方向是从高地址到低地址,栈底的占领着最高内存地址,先入栈的参数,其地理位置也就最高了)
5. c.addr = b.addr + x_sizeof(b);  
b.addr = a.addr + x_sizeof(a);
6.void var_args_func(const char * fmt, ... )
第一个可变参数的位置应该是:first_vararg.addr = fmt.addr + x_sizeof(fmt);
var_args_func(const char * fmt, ... ) 函数中,可变参数的位置了。起码第一个可变参数的位置应该是:first_vararg.addr = fmt.addr + x_sizeof(fmt);  根据这一结论我们试着实现一个支持可变参数的函数:
7.
void var_args_func(const char * fmt, ... )
{   char    *ap;
ap = ((char*)&fmt) + sizeof(fmt);
printf("%d\n", *(int*)ap);          //4
ap =  ap + sizeof(int);
printf("%d\n", *(int*)ap);          //5
ap =  ap + sizeof(int);
printf("%s\n", *((char**)ap));      //hello world
}
int main()
{
var_args_func("%d %d %s\n", 4, 5, "hello world");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值