举例
#include <stdarg.h>
#include <string>
using namespace std;
void va_add(int cnt, ...)
{
va_list ap;
va_start(ap, cnt);
int sum = 0;
for (int i = 0; i < cnt; ++i)
sum += va_arg(ap, int);
va_end(ap);
printf("%d\n", sum);
}
int main()
{
va_add(3, 1, 2, 3); //6
va_add(4, 1, 2, 3, 4); //10
return 0;
}
函数接口详解
带可变参数函数的实现使用了指针参数来解决参数的可变问题,指针参数随着其移动指向不同的参数,C语言的函数形参是从右向左压入堆栈的,以保证栈顶是第一个参数。
C语言标准库中头文件<stdarg.h>索引的接口包含了一组能够遍历变长参数列表的宏。
va_list(定义指针)
用来定义一个表示参数表中各个参数的变量,即定义了一个指向参数的指针, 用于指向可选的参数。
va_start(ap, args) (初始化指针)
使参数列表指针ap指向函数参数列表中的第一个可选参数,args是位于第一个可选参数之前的固定参数,或者说最后一个固定参数。通常用于指定可变参数列表中参数的个数。
如函数的声明是void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数v为c,因此就是va_start(ap, c)。
va_arg(ap, type)
返回参数列表中指针ap所指的参数,返回类型为type。并使指针ap指向参数列表中下一个参数。返回的是可选参数,不包括固定参数。
va_end(ap)
清空参数列表,并置参数指针arg_ptr无效。
###3、一个实例my_printf
#define _CRT_SECURE_NO_WARNINGS
#include <cstdarg>
#include <cstdlib>
#include <cstdio>
#include <ctime>
size_t my_print(const char *fmt, ...)
{
char buf[2000];
time_t t;
struct tm *p;
time(&t); //获取1970年1月1日到现在的秒数保存到t中
p = gmtime(&t); //将t中的秒数转换为实际日期的表示格式
size_t len = sprintf(buf, "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d]",
p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
va_list argptr;
va_start(argptr, fmt);
size_t cnt = vsprintf(buf + len, fmt, argptr);
len += cnt;
va_end(argptr);
puts(buf);
return len;
}
int main()
{
printf("%d", my_print("%s%s %s %s", "Wtf?", "What", "are you", "nong sha le!!!"));
system("pause");
return 0;
}
还有一种方法则是使用C++11中的可变参数模板(
函数模板
)也可以实现。
版权声明:本文为weixin_43971373原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。