#include <stdio.h>
#include <stdarg.h> //要包含这个头文件
void variable(int i, ...)
{
int j = 0;
va_list arg_ptr; //第1步,定义这个指向参数列表的变量,把这个换成 char*试一试?
va_start(arg_ptr, i);//第2步,把上面这个变量初始化.即让它指向参数列表
while(j != -1 )
{
//第3步,获取arg_ptr指向的当前参数.这个参数的类型由va_arg的第2个参数指定
j = va_arg(arg_ptr, int);
printf("%d ",j );
}
va_end(arg_ptr); //第4步,做一些清理工作
}
int main()
{
variable(3, 3,4, 5,6, -1);
return 0;
}
//
//
//
///作为va_list,va_start的练习,可以学习一下使用_vsnprintf函数
#include<stdio.h>
#include <stdarg.h>
void formatoutput(char* format, ...)
{
chars[10];
va_list arg_ptr;
va_start(arg_ptr, format);
_vsnprintf(s, sizeof(s)-1, format,arg_ptr);
printf("%s ", s);
}
void main()
{
formatoutput("%s%s","d","g");
}
/
参数个数不定的函数,最频繁使用的就是printf()与scanf()。其实,我们也可以自己实现这样的功能,首先看
一个例子:
#include<stdio.h>
#include<stdarg.h>
int Sum(int first,int second, ...)
{
int sum = 0, t = first;
va_list vl;
va_start(vl, first);
while (t != -1)
{
sum += t;
t = va_arg(vl, int);//将当前参数转换为int类型
}
va_end(vl);
return sum;
}
int main(int argc,char* argv[])
{
printf("The sum is %d\n", Sum(30, 20, 10, -1));//-1是参数结束标志
return 0;
}
#include<stdio.h>
int Sum(int first,int second, ...)
{
int sum = 0, t = first;
char * vl;//定义一个指针
vl = (char *)&first;//使指针指向第一个参数
while (*vl != -1)//-1是预先给定的结束符
{
sum += *(int *)vl;//类型转换
vl += sizeof(int);//移动指针,使指针指向下一个参数
}
return sum;
}
int main(int argc,char* argv[])
{
printf("The sum is %d\n", Sum(30, 20, 10, -1));//-1是参数结束标志
return 0;
}
可以看出,通过使用指针的确实现了参数个数不定的函数了,但是程序中还有一个问题,那就是移动指针,在
void myPrint(constchar *frm, ...)
{
va_listvl;
va_start(vl,frm);
vprintf(frm,vl);
va_end(vl);
}
如: void foo(...);
void foo(parm_list,...);
void foo(...)
{
}
调用:foo(a,b,c);
就是不懂,把a,b,c的值传进函数里面后,用什么变量来接收???如果不能接收,(...)岂不是没意义?
还有就是不明白
int printf(const char*...);
printf("hello,&s\n",userName);
这个c的输出函数是怎么用(...)实现的.
先谢了:)
Re:
首先函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。像这段代码:
void TestFun(char* pszDest, int DestLen, const char* pszFormat,...)
{
va_list args;
va_start(args, pszFormat);
_vsnprintf(pszDest, DestLen, pszFormat, args);
va_end(args);
}
一个简单的可变参数的C函数
//示例代码1:可变参数函数的使用
#include"stdio.h"
#include "stdarg.h"
void simple_va_fun(int start, ...)
{
va_list arg_ptr;
int nArgValue =start;
int nArgCout=0; //可变参数的数目
va_start(arg_ptr,start); //以固定参数的地址为起点确定变参的内存起始地址。
do
{
++nArgCout;
printf("the %d th arg: %d",nArgCout,nArgValue); //输出各参数的值
nArgValue =va_arg(arg_ptr,int); //得到下一个可变参数的值
} while(nArgValue !=-1);
return;
}
int main(int argc, char* argv[])
{
simple_va_fun(100,-1);
simple_va_fun(100,200,-1);
return 0;
}
⑴由于在程序中将用到以下这些宏:
voidva_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
va在这里是variable-argument(可变参数)的意思。
⑵函数里首先定义一个va_list型的变量,这里是arg_ptr,这个变量是存储参数地址的指针.因为得到参数的地址之后,再结合参数的类型,才能得到参数的值。
⑶然后用va_start宏初始化⑵中定义的变量arg_ptr,这个宏的第二个参数是可变参数列表的前一个参数,即最后一个固定参数。
⑷然后依次用va_arg宏使arg_ptr返回可变参数的地址,得到这个地址之后,结合参数的类型,就可以得到参数的值。
⑸设定结束条件,这里的条件就是判断参数值是否为-1。注意被调的函数在调用时是不知道可变参数的正确数目的,程序员必须自己在代码中指明结束条件。至于为什么它不会知道参数的数目,在看完这几个宏的内部实现机制后,自然就会明白。
1)可变参数的存储形式.
大家都知道,一般函数的形参属于局部变量.而局部变量就是存储在内存的栈区(所谓的栈区:由编译器自动分配释放,
存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。).可变参数也是存储在内存栈区.
在对函数的形参存储的时侯,编译器是从函数的形参的右边到左边逐一地压栈,
这样保证了栈顶是函数的形参的第一个参数(从左到右数).而80x86平台下的内存分配顺序是从高地址内存到低地址内存.
因此,函数的形参在内存的存储形式如下图(以fun(int var1,int var2,...,int var3,intvar4)为例):
栈区:
|栈顶
|第一个固定参数var1
|可变参数前的第一个固定参数var2
|可变参数的第一个参数
|...
|可变参数的最后一个参数
|函数的倒数第二个固定参数var3
|函数的最后一个固定参数var4
|...
|函数的返回地址
|...
|栈底