重复使用变元函数参数不会;不起作用
Repeated use of a variadic function argument doesn't work
我有一个函数,试图将内容记录到控制台和日志文件中,但它不起作用。第二次使用可变长度参数会将垃圾写入控制台。有什么想法吗?
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);
}
原始代码失败,因为它试图在需要使用vprintf()
的地方使用printf()
。考虑到像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);
}
没有特别要求使用两个单独的va_list
变量;只要在再次使用CCD_ 8之前使用va_end()
,就可以使用同一个两次
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);
}
当一个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);
}
请注意,在此代码中,调用代码负责在args1
上调用va_end()
。事实上,标准上说:
va_start
和va_copy
宏的每次调用应通过相同函数中CCD_ 20宏的相应调用来匹配。
由于logVprintf()
函数不调用va_start
或va_copy
来初始化args1
,因此它不能合法地在args1
上调用va_end
。另一方面,标准要求它为args2
调用va_end
。
logPrintf()
功能现在可以按照logVprintf()
实现:
void logPrintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
logVprintf(fmt, args);
va_end(args);
}
这种结构——一个采用va_list
的运算函数和一个采用省略号(变量参数)并在转换为va_list
后将其传递给运算函数的覆盖函数——通常是一种很好的工作方式。您通常迟早会发现需要一个带有va_list
参数的版本。
升级编译器,这更像C++:
template <typename... Args>
void logPrintf(const char *fmt, Args&&... args) {
logOpen;
fprintf(flog, fmt, args...);
logClose;
printf(fmt, args...);
}
当然,提供CCD_ 34和CCD_。
我认为这种方式更有意义:
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);
}
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- 我正在开发服务器,ip作为参数传递不起作用
- G++ C++17 类模板参数推导在非常特殊的情况下不起作用
- 类中的虚拟布尔函数参数不起作用
- 模板 ctor 类型推导不起作用(没有匹配的构造函数用于初始化 ...)与函数<>参数
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- 为什么重载运算符>在参数声明 const 时不起作用?
- 为什么当我提供一些模板参数时,C++17 模板类推导不起作用?
- 为什么static_assert在带有 const 参数的成员函数中不起作用?
- 将参考类型作为嵌套模板结构中的模板参数作为模板参数不起作用
- C++ 数组参数不起作用
- sscanf 格式参数不起作用
- 我无法正确获取这些变量声明...为什么这些参数不起作用?我只是将 n 值设置为数组长度
- DrawImage高度参数不起作用
- C++ 默认函数参数不起作用
- 输入参数不起作用
- 处理C++中的参数不起作用
- 以双精度数除以双精度数来获得循环中的余数和char参数不起作用
- VIM omnicppcomplete对函数参数不起作用
- 模板模板参数不起作用