va_list
va_list定义于头文件中,是用于处理C语言风格变参函数而使用的一种对象类型,va_list类型的变量是指向参数的指针,通过指针运算来调整访问的对象,其主要使用如下几种宏来进行操作.
va_start
宏的函数原型如下:
void va_start( std::va_list ap, parm_n );
va_start 宏允许访问后随具名参数 parm_n 的可变参数。可以认为是va_list的初始化操作, parm_n是首个可变参数前紧接的具名参数。va_start总应该在av_arg之前调用.
va_end
定义如下:
void va_end( va_list ap );
该宏用于对va_start或va_copy初始化的对象进行清理,修改va_list,使其不再可用。
va_arg
宏的函数原型如下:
T va_arg( std::va_list ap, T );
可以使用该宏用于将va_list展开成下一个参数的T类型表达式。每次调用后,va_list对象都会改变,使其指向下一个可变参数。试用示例如下:
#include <iostream>
#include <cstdarg>
int count(int num, ...)
{
va_list args;
va_start(args, num);
int cot = 0;
for (int i = 0; i < num; i++)
cot += va_arg(args, int); //每次展开一个参数
return cot;
}
int main() {
std::cout << count(5, 1, 2, 3, 4, 5) << std::endl;
return 0;
}
//输出15
va_arg的调用有如下的注意事项:
- va_arg操作的对象必须先被va_start初始化,并且中间没有进行过va_end
- 若av_list的下一个参数与T不吻合,则行为未定义
- 若av_list无更多参数,则行为也未定义
va_copy(C++11)
C++11后才有的宏,用于av_list的拷贝,定义如下:
void va_copy( std::va_list dest, std::va_list src );
对应的各种输出函数
int vprintf( const char* format, std::va_list vlist );
int vfprintf( std::FILE* stream, const char* format, std::va_list vlist );
int vsprintf( char* buffer, const char* format, std::va_list vlist );
int vsnprintf( char* buffer, std::size_t buf_size, const char* format, std::va_list vlist );
这些函数分别从 vlist 所定义的位置,转换之为字符串等价版本,并将结果写入到各种池。各种参数的含义如下:
- stream: 要写入的输出文件流
- buffer: 用于保存结果的字符串指针
- buf_size: 要写入的最大字符数
- format: 格式化字符串,用于指定格式化字符串的方式
- vlist: 可变参数列表,包含格式化字符串的可变参数
示例代码如下:
#include <iostream>
#include <cstdio>
#include <cstdarg>
#include <string>
std::string format(const char* fmt, ...)
{
va_list vlist;
va_start(vlist, fmt);
char buf[128];
vsprintf(buf, fmt, vlist);
va_end(vlist);
return std::string(buf);
}
int main() {
std::string str = format("%s %s %d", "hello", "world", 1);
std::cout << str << std::endl;
return 0;
}
//输出: hello world 1