我找到了一种在C ++中传递可变长度数组的方法。但是它在下面的代码中无法执行“包装”功能。实际上,我想在我的项目中包装格式功能。
我的代码在做什么错?
测试代码
#include <iostream>
#include <stdarg.h>
#include <string>
void log(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);
int length = _vscprintf(format, argptr);
char* buf_ = new char [length + 1];
int ret = vsnprintf(buf_, 1000, format, argptr);
if (ret >= 0) {
std::cout << buf_ << std::endl;
}
delete[] buf_;
va_end(argptr);
}
void wrap(const char *format, ...)
{
va_list ap;
va_start(ap, format);
log(format, ap);
va_end(ap);
}
int main()
{
log( "direct = %d", 1);
wrap("wrap = %d", 1);
return 0;
}
结果就在这里。
direct = 1
wrap = 15137088 // what's happen?
最佳答案
我找到了一种在C ++中传递可变长度数组的方法
那不是可变长度的数组,也不是真正的C ++语言。 ...
是变长参数列表,在C语言中可用。
包装您的日志函数的最简单合理的方法是可变参数模板,它可以简单地写为:
template <typename... Args>
void wrap(const char *format, Args&&... args) {
log(format, std::forward<Args>(args)...);
}
在日志函数本身中,
vsnprintf
返回在缓冲区已满的情况下应写入的字节数。因此,您始终可以使用乐观的缓冲区大小对其进行一次调用,并在必要时增大缓冲区:您不需要非标准的_vscprintf
。看起来像:void log(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);
static const size_t DefaultSize = 200;
// pick some value that makes sense ^^ here
char buf[DefaultSize];
int rv = vsnprintf(buf, DefaultSize, format, argptr);
if (rv < 0) {
// we can't return errors with this prototype:
// should it throw?
return;
}
if (rv >= DefaultSize) {
vector<char> dynbuf(rv+1);
rv = vsnprintf(&dynbuf[0], dynbuf.size(), format, argptr);
std::cout << &dynbuf[0] << std::endl;
} else {
std::cout << buf << std::endl;
}
va_end(argptr);
}
还要注意,
wrap
知道其所有参数的类型,但是当您调用C风格的可变参数函数log
时,该信息将被丢弃。您可能认为Boost.Format是类型安全的替代方法-额外的好处是,它将为您管理缓冲区。关于c++ - 如何在C++中接收可变长度数组的函数中传递可变长度数组?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28627343/