‘壹’ va_list是什么变量结构在哪个头文件定义的
头文件为#include 〈stdarg.h〉,是在c语言中解决变参问题的一组宏。
在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。
有些库中va_list实现为char* 指针,可变参数的函数原理其实很简单,而VA系列是以宏定义来定义的,实现跟堆栈相关。
‘贰’ 【求解释va_list、va_start、va_arg、va_end】
这些都C定义的一些宏
获取省略号指定的参数: 在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。
va_start使arg_ptr指向第一个可选参数。
va_arg返回参数列表中的当前参数并使arg_ptr指向参数列表中的下一个参数。
va_end把arg_ptr指针清为NULL。
函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。
‘叁’ C语言关于文件中va_list的问题
不确定参数个数的函数要用省略号方式写
void error_msg(char *format,...)
‘肆’ ...的C语言中的元运算符
可变参数函数(Variadic functions)是stdarg.h内容典型的应用,虽然也可以使用在其他由可变参数函数调用的函数(例如,vprintf)。 可变参数函数的参数数量是可变动的,它使用省略号来忽略之后的参数。例如printf函数一般。代表性的声明为:
int check(int a, double b, ...);
可变参数函数最少要有一个命名的参数,所以
char *wrong(...);
在C中是不被允许的(在C++中,这样的声明是合理的)。C中,省略符号之前必须要有逗号;而在C++中,则没有这种强制要求。 使用相同的语法来定义: longfunc(char,double,int,...);longfunc(chara,doubleb,intc,...){/*...*/}//在C的旧形式中可能会出现较省略的函数定义:longfunc();chara;doubleb;longfunc(a,b,c,...){/*...*/}访问未命名的参数,首先必须在可变参数函数中声明va_list类型的变量。调用va_start并传入两个参数:第一个参数为va_list类型的变量,第二个为省略号前最后一个有名字的参数的名称,接着每一调用va_arg就会返回下一个参数,va_arg的第一个参数为va_list,第二个参数为返回的类型。最后va_end必须在函数返回前被va_list调用(va_list当作参数)(没有要求要读取完所有参数)。
C99提供额外的宏,va_,它能够复制va_list。而va_(va2, va1)函数作用为拷贝va1到va2。
没有机制定义该怎么判别传递到函数的参数量或者数据类型。函数通常需要知道或确定它们变化的方法。共通的惯例包含:
使用printf或scanf类的格式化字串来嵌入明确指定的类型。
在可变参数最后的标记值(sentinel value)。
总数变量来指明可变参数的数量。
‘伍’ C语言 函数变参数的问题(va_list,va_start,va_arg,va_end)
va_start (ap, num);
这句话用错了,va_start 是用来初始化ap的,num应该改为传递的第一个对象,也就是item。
loc_item = va_arg(ap,Item);
这句的作用是loc_item 被赋给ap的下一对象的值。
#include <stdio.h>
#include <stdarg.h>
typedef struct item
{
char name[20];
char kind[20];
}Item;
void showname (Item locitem,...);
void main ()
{
Item locitem1 = {"aaa","aaa"};
Item locitem2 = {"bbb","bbb"};
showname (locitem1,locitem2);
}
void showname (Item item,...)
{
va_list ap;
Item loc_item;
va_start (ap, item);//修改了这里
loc_item = va_arg(ap,Item);
printf("%s is %s\n",loc_item.name,loc_item.kind);
printf("other:%s is %s\n",item.name,item.kind);
va_end (ap);
}
显示结果为:
bbb is bbb
other:aaa is aaa
‘陆’ c语言如何封装一个带有可变参数的方法
需要借用C语言的VA_LIST宏定义,及相关操作来实现可变参数。
VA_LIST所在头文件:#include <stdarg.h>,用法如下:
(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
(2)然后用VA_START宏初始化刚定义的VA_LIST变量;
(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
(4)最后用VA_END宏结束可变参数的获取。
以下是一个自定义打印接口的实现:
intmy_printf(constchar*fmt,...)//...表示参数可变
{
va_listargs;//定义va_list
staticchargc_PrintfOutBuff[1000];
va_start(args,fmt);//初始化
vsnprintf((char*)gc_PrintfOutBuff,1000,(char*)fmt,args);//这里没有使用VA_ARG取回单个变量,而是借用vsnprinf一次性读取。
va_end(args);//结束获取
puts("%s",(constchar*)gc_PrintfOutBuff);//使用。
return0;
}
‘柒’ typedef struct __va_list { void *__ap; } va_list什么意思
定义va_list为结构体struct __va_list { void *__ap; }的名字。
因此,可以用
va_list astruct;
来定义,代替
struct __va_list astruct;
‘捌’ C语言 函数变参数的问题(va_list,va_start,va_arg,va_end)
void showname (int num,...);//第一个参数最好存放参数个数
showname (2,locitem1,locitem2);//调用
void showname (int num,...)
{
va_list ap;
Item loc_item;
va_start (ap, num);
for(;num;num--){
loc_item = va_arg(ap,Item);
printf("%s is %s\n",loc_item.name,loc_item.kind);
}
va_end (ap);
}
va_start (ap, num);通过判断num的长度来确定 变长参数列表里第一个参数的地址
所以它判断的不是num的值而是num所占内存的大小