c语言可变参数使用,C语言可变参数的使用

先来个简单的例子:#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.0中x86平台的定义:

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                  |第二个参数var2                  后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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值