来自具有可变数量参数的函数的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 ++答案(如果存在差异)
我觉得我错过了一些明显但却无法解决的问题
你做到了。这是你真正开始的事情:“只使用这些功能的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函数只关心需要对列表执行的操作,这是允许在此重用的内容。
编辑前注意事项:BTW,如果C兼容性确实是一个问题,函数原型需要一个逗号来将最后一个参数与省略号分开。您使用的语法仅限C ++。
您不能将调用链接到C风格的可变参数函数。唯一的方法是通过va_list
作为参数。这正是为什么需要v *系列函数的原因。
因此,您根据va_list
编写类似v *的函数,然后将每个函数包装在基于省略号的可变参数函数中。