今天在看代码的时候,看到了这样一段调试的代码,搞不清楚(...)这个是什么意思,看了下相关资料,简单记录下。
#ifdef DEBUG
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)
#else
#define DBG(...)
#endif
1、printf代码
1 2 |
|
如何编写可变参数函数呢?我们首先来看看printf函数原型是如何定义的。
在linux下,输入man 3 printf,可以看到prinf函数原型如下:
1 2 3 |
|
后面的三个点...表示printf参数个数是不定的.
如何实现可变参数函数?
2. 编写可变函数准备
为了编写可变参数函数,我们通常需要用到<stdarg.h>头文件下定义的以下函数:
1 2 3 4 |
|
其中:
va_list是用于存放参数列表的数据结构。
va_start函数根据初始化last来初始化参数列表。
va_arg函数用于从参数列表中取出一个参数,参数类型由type指定。
va_copy函数用于复制参数列表。
va_end函数执行清理参数列表的工作。
上述函数通常用宏来实现,例如标准ANSI形式下,这些宏的定义是:
1 2 3 4 5 |
|
使用宏_INTSIZEOF是为了按照整数字节对齐指针,因为c调用协议下面,参数入栈都是整数字节(指针或者值)。
4、用va_list实现vprintf()示例
#include <stdio.h>
#include <stdarg.h>
void my_printf(const char *format, ...)
{
int n;
va_list arg_list;
va_start(arg_list, arg_list);
n = vprintf(format, arg_list);
va_end(arg_list);
}
int main(int argc, char *argv[])
{
int ai = 0;
my_printf("%d\n", ai);
return 0;
}
5、C语言可变参数函数简单实例
参数列表的格式是强制性参数在前,后面跟着一个逗号和省略号(...),这个省略号代表可选参数。
可变参数函数要获取可选参数时,必须通过一个类型为 va_list 的对象,它包含了参数信息。这种类型的对象也称为参数指针(argument pointer),它包含了栈中至少一个参数的位置。可以使用这个参数指针从一个可选参数移动到下一个可选参数,由此,函数就可以获取所有的可选参数。va_list 类型被定义在头文件 stdarg.h 中。
一个简单的例子,说明可变参数的用法
#include <stdio.h>
#include <stdarg.h>
int simple(int num,...) //num代表了要传递的可变参数的总数
{
int i, result=0;
va_list vl; //va_list指针,用于va_start取可变参数,为char*
va_start(vl,num); //取得可变参数列表中的第一个值
printf("num:%d, vl:%d\n",num,*vl);
//访问所有赋给valist的值
for (i = 0; i < (num-1); i++)//这里num表示可变参数列表中有多少个参数
{
//这里把vl往后跳过4个字节(sizeof(int)大小)指向下一个参数,返回的是当前参数(而非下一个参数)
result = va_arg(vl, int);
//这里打印下,可以看出,vl总是指向result后面的那个参数
printf("in for result:%d, *vl:%d\n", result, *vl);
}
va_end(vl);//结束标志
return result;
}
int main(int argc, char **argv)
{
simple(5,1,2,3,4,5);
return 0;
}
运行结果如下:
原文地址:http://www.runoob.com/cprogramming/c-variable-arguments.html