va_start、va_end获取可变参数

首先,函数的参数以栈的形式存取,在存放时,从右到左开始入栈,所以在函数执行时,将函数的最左边第一个参数先入栈。因此可以以函数的参数列表的确定的最后一个参数的地址,通过指针移位和指定数据类型来获取函数的可变参数。

 <stdarg.h>头文件中的相关宏定义

#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))

当前可变参数的地址加上下一可变参数对其的偏移量的就是下一可变参数的地址了(va_arg的实现)。这里提到的偏移量并不一定等于参数所占的字节数,而是为参数所占的字节数再扩展为机器字长(acpi_native_int)倍数后所占的字节数(因为入栈操作针对的是一个机器字),这也就是为什么_bnd那么定义的原因。

typedef char* va_list;   //va_list表示可变参数列表类型
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))      // va_start用于获取函数参数列表中可变参数的首指针(获取函数可变参数列表)
  * 输出参数ap(类型为va_list): 用于保存函数参数列表中可变参数的首指针(即,可变参数列表)
  * 输入参数A: 为函数参数列表中最后一个固定参数

#define va_arg(ap, T) (*(*)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))         // va_arg用于获取当前ap所指的可变参数并将并将ap指针移向下一可变参数
  * 输入参数ap(类型为va_list): 可变参数列表,指向当前正要处理的可变参数
  * 输入参数T: 正要处理的可变参数的类型
  * 返回值: 当前可变参数的值

void va_end ( va_list ap );      //释放ap申请的空间

例:

#include 〈stdio.h〉 
#include 〈string.h〉 
#include 〈stdarg.h〉 

/*函数原型声明,至少需要一个确定的参数,注意括号内的省略号*/ 
int demo( char, ... ); 
void main( void ) 

   demo("DEMO", "This", "is", "a", "demo!", ""); 


/*ANSI标准形式的声明方式,括号内的省略号表示可选参数*/ 
int demo( char msg, ... ) 

       /*定义保存函数参数的结构*/
   va_list argp; 
   int argno = 0; 
   char para; 
     /*argp指向传入的第一个可选参数,msg是最后一个确定的参数*/ 
   va_start( argp, msg ); 
   while (1) 
       { 
        para = va_arg( argp, char); 
           if ( strcmp( para, "") == 0 ) 
               break; 
           printf("Parameter #%d is: %s\n", argno, para); 
           argno++; 

va_end( argp ); 
/*将argp置为NULL*/
return 0; 
}

当然也可以指定可变参数,例:

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

char buffer[80];
int vspfunc(char *format, ...)
{
   va_list aptr;
   int ret;

   va_start(aptr, format);
   ret = vsprintf(buffer, format, aptr);  
//vsprintf将aptr按照format规定的格式输入到buffer里面
va_end(aptr);
   return(ret);
}
int main()
{   int i = 5;  
 float f = 27.0; 
  char str[50] = "runoob.com";  
 vspfunc("%d %f %s", i, f, str);  
 printf("%s\n", buffer);     
 return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

5 27.000000 runoob.com


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

picaso77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值