我找到了一种在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/

10-13 06:51