Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2414543
  • 博文数量: 298
  • 博客积分: 7876
  • 博客等级: 准将
  • 技术积分: 5500
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-23 13:39
文章存档

2013年(2)

2012年(142)

2011年(154)

分类: WINDOWS

2011-04-13 23:05:10

先来个简单的例子:
#include

#include

void test0(int num,...)

{

 va_list ap;

 va_start(ap, num);

 while(num--)

 {

  printf("%s ",va_arg(ap, char *));

 }

 va_end(ap);

}

void test1(int num,...)

{

 va_list ap;

 va_start(ap, num);

 while(num--)

 {

 

  printf("%d ",va_arg(ap, int *));//为什么输出正确结果呢??

 }

 va_end(ap);

 printf("\n");

}

void test2(int num,...)

{

 va_list ap;

 va_start(ap, num);

 while(num--)

 {

  printf("%d ",va_arg(ap, int));

 }

 va_end(ap);

 printf("\n");

}

void test3(int num,...)

{

 

 va_list ap;

 va_start(ap, num);

 while(num--)

 {

  printf("%c ",va_arg(ap, char));

 }

 va_end(ap);

 printf("\n");

}

int main()

{

 test0(3, "hello", "world", "!\n");    

 test1(4, 1, 2, 3 ,4);

 test2(2, 1, 2, 3 ,4);

 test2(3, '1', '2', '3' ,'4');

 

 return 0;

}

输出:

hello world !

 1 2 3 4

1 2

49 50 51//为什么不能输出 1 2 3??

  

  可变参数中个数不定可是传入的是一个参数也可以是多个;可变参数中的每个参数的类型可以不同,也可以相同;可变参数的每个参数并没有实际的名称与之相对应,用起来是很灵活。
      
可变参数是由宏实现的,但是由于硬件平台的不同,编译器的不同,宏的定义也不相同,下面是VC6.0x86平台的定义:

typedef char * va_list;     // TC中定义为void*
#define _INTSIZEOF(n) 

  ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) //为了满足需要内存对齐的系统,求int型大小
#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 ) t
为变量类型

      C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数,而且x86平台内存分配顺序是从高地址到低地址。因此似函数fun(int var1,int var2,...,int varN)内存分配大致上是这样的:(可变参数在中间)
栈区:
|
栈顶             低地址
|
第一个参数var1                  <-- &v
|
第二个参数var2                  <-- va_start(ap,v)ap指向地址      
|...
|
函数的最后varN
|...
|
函数的返回地址
|...
|
栈底    高地址
va_start(ap,v)
;后ap = (va_list)&v + _INTSIZEOF(v)指向第二个参数地址
调用va_arg(ap,t)  ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )取出当前ap指针所指的值,并使ap指向下一个参数

不过被定义为宏的东西用起来要小心,我现在用不着va_list,不过先了解点皮毛也好。

下面是msdn中的例子: beautiful

#include

#define ANSI            /* Comment out for UNIX version     */

#ifdef ANSI             /* ANSI compatible version          */

#include

int average( int first, ... );

#else                   /* UNIX compatible version          */

#include

int average( va_list );

#endif

void main( void )

{

   /* Call with 3 integers (-1 is used as terminator). */

   printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );

   /* Call with 4 integers. */

   printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );

   /* Call with just -1 terminator. */

   printf( "Average is: %d\n", average( -1 ) );

}

/* Returns the average of a variable list of integers. */

#ifdef ANSI             /* ANSI compatible version    */

int average( int first, ... )

{

   int count = 0, sum = 0, i = first;

   va_list marker;

   va_start( marker, first );     /* Initialize variable arguments. */

   while( i != -1 )

   {

      sum += i;

      count++;

      printf(" %d sum: %d", i, sum);

      i = va_arg( marker, int);

     

   }

   va_end( marker );              /* Reset variable arguments.      */

   return( sum ? (sum / count) : 0 );

}

#else       /* UNIX compatible version must use old-style definition.  */

int average( va_alist )

va_dcl

{

   int i, count, sum;

   va_list marker;

   va_start( marker );            /* Initialize variable arguments. */

   for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )

      sum += i;

   va_end( marker );              /* Reset variable arguments.      */

   return( sum ? (sum / count) : 0 );

}

#endif

结果:

2 sum: 2 3 sum: 5 4 sum: 9Average is: 3

 5 sum: 5 7 sum: 12 9 sum: 21 11 sum: 32Average is: 8

Average is: 0

Press any key to continue

在来一个简单的例子:
#include
#include

void print(char *format,...);    //自定义输出格式
void print(char *format,...)
{
 va_list argptr;
 va_start(argptr, format);
 while(*format != '\0')
 {
  switch(*(format++))
  {
  case 's': printf("%s ", va_arg(argptr, char *)); break;
  case 'i': printf("%d ", va_arg(argptr, int)); break;
  case 'c': printf("%c ", va_arg(argptr, char)); break;
  case 'f': printf("%.1f\n", va_arg(argptr, double)); break;
  default: break;
  }
 }
 va_end(argptr);
}
int main()
{
 print("sicft","laomou",24,'M',120.0);    //
输出格式依次为 string, integer, char, float
 return 0;
}

 

阅读(903) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~