从具有可变参数数量的函数进行的printf
类调用很容易进行-只需使用这些函数的 v 版本(vprintf
vsprintf
,CString::FormatV
等)。但是,如果我将呼叫链接起来怎么办?这是简单的代码:
#include <stdarg.h>
#include <iostream>
void direct(const char * _fmt, bool _extra, ...){
va_list args;
va_start(args, _extra);
char ca[200];
vsprintf(ca, _fmt, args);
std::cout << ca << std::endl;
va_end(args);
}
void chained(const char * _fmt, ...){
va_list args;
va_start(args, _fmt);
direct(_fmt, false, args);
va_end(args);
}
int main(){
direct("direct works just fine: %d", false, 1);
chained("indirect produces garbage: %d", 1);
return 0;
}
示例输出如下:
direct works just fine: 1
indirect produces garbage: 1951661256
我觉得我缺少明显的东西,但到目前为止还无法弄清楚。请帮我修复它,以便无论我叫direct
还是chained
都可以正常工作。
将问题标记为C / C ++,但我更喜欢C ++答案(如果有所不同)
答案 0 :(得分:5)
我觉得我缺少明显的东西,但到目前为止还无法弄清
您做到了。这实际上是您开始的:“只需使用这些功能的v版本” 。这些函数获得v版本的原因是允许将它们链接起来,就像您所说的那样。因此,如果您想为自己的类似于printf的功能支持它,请确保遵循相同的做法:
void direct_v(const char * _fmt, bool _extra, va_list args){
char ca[200];
vsprintf(ca, _fmt, args);
std::cout << ca << std::endl;
}
void direct(const char * _fmt, bool _extra...){
va_list args;
va_start(args, _extra);
direct_v(_fmt, _extra, args);
va_end(args);
}
void chained(const char * _fmt...){
va_list args;
va_start(args, _fmt);
direct_v(_fmt, false, args);
va_end(args);
}
像这样拆分direct
的一个很好的新兴属性是,您可以更好地分离关注点。包装器执行va_list
相关位,而v函数仅关心列表需要完成的操作,因此可以在此处重用。
预编辑说明:顺便说一句,如果确实需要C兼容性,则函数原型需要使用逗号将最后一个参数与省略号分开。您使用的语法仅是C ++。
答案 1 :(得分:0)
您不能链式调用C风格的可变参数函数。唯一的方法是将va_list
作为参数传递。这正是需要v *系列功能的原因。
因此,您可以根据va_list
编写类似v *的函数,然后然后将每个函数包装在基于省略号的可变参数函数中。