Ned*_*die 13 c c++ variadic variadic-functions
我有一个函数,试图将东西记录到控制台和日志文件,但它不起作用.第二次使用变长参数会将垃圾写入控制台.有任何想法吗?
void logPrintf(const char *fmt, ...) {
va_list ap; // log to logfile
va_start(ap, fmt);
logOpen;
vfprintf(flog, fmt, ap);
logClose;
va_end(ap);
va_list ap2; // log to console
va_start(ap2, fmt);
printf(fmt, ap2);
va_end(ap2);
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*ler 12
原始代码失败,因为它尝试使用printf()它需要使用的位置vprintf().采用像面部值logOpen和logClose语句一样的可疑点(给出符号,可能是它们是打开和关闭flog文件流的宏),代码应该是:
void logPrintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
logOpen;
vfprintf(flog, fmt, ap);
logClose;
va_end(ap);
va_list ap2;
va_start(ap2, fmt);
vprintf(fmt, ap2);
va_end(ap2);
}
Run Code Online (Sandbox Code Playgroud)
没有特别要求使用两个单独的va_list变量; 在再次使用之前,使用相同的两倍是完全可以的.va_end()va_start()
void logPrintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
logOpen;
vfprintf(flog, fmt, ap);
logClose;
va_end(ap);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
Run Code Online (Sandbox Code Playgroud)
当一个va_list值传递给另一个函数(vfprintf()并vprintf()在此代码中)时,您应该假定它在当前函数中不再可用.打电话是安全的va_end().
va_copy()此代码中没有必要.它有效,但不需要.您需要va_copy()在其他情况下,当你的函数传递一个如va_list你需要处理列表两次:
void logVprintf(const char *fmt, va_list args1)
{
va_list args2;
va_copy(args2, args1);
logOpen;
vfprintf(flog, fmt, args1);
logClose;
vprintf(fmt, args2);
va_end(args2);
}
Run Code Online (Sandbox Code Playgroud)
请注意,在这段代码,它是调用代码的责任调用va_end()上args1.的确,标准说:
每次调用
va_start和va_copy宏都应该通过va_end相同函数中宏的相应调用来匹配.
由于该logVprintf()功能不调用任何va_start或va_copy初始化args1,就不能合法地调用va_end上args1.在另一方面,标准要求它打电话va_end了args2.
该logPrintf()功能现在可以实现logVprintf():
void logPrintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
logVprintf(fmt, args);
va_end(args);
}
Run Code Online (Sandbox Code Playgroud)
这个结构 - 一个操作函数,它接受一个va_list带有省略号(变量参数)的覆盖函数,并在转换为va_list- 后将它们传递给操作函数,这通常是一种很好的工作方式.迟早,您通常会发现需要带有va_list参数的版本.
Ton*_*ion -2
我认为这种方式更有意义:
void logPrintf(const char *fmt, ...) {
va_list ap; // log to logfile
va_start(ap, fmt);
logOpen;
vfprintf(flog, fmt, ap); //logfile
printf(fmt, ap); //console
logClose;
va_end(ap);
}
Run Code Online (Sandbox Code Playgroud)