链接可变函数调用

问题描述 投票:1回答:2

来自具有可变数量参数的函数的printf函数式调用很容易实现 - 只需使用这些函数的v版本(vprintfvsprintfCString::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

我觉得我错过了一些明显但却无法解决的问题。请帮我修复它,以便我调用directchained代码正常工作。

将问题标记为C / C ++,但我更喜欢C ++答案(如果存在差异)

c++ c variadic-functions
2个回答
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函数只关心需要对列表执行的操作,这是允许在此重用的内容。


编辑前注意事项:BTW,如果C兼容性确实是一个问题,函数原型需要一个逗号来将最后一个参数与省略号分开。您使用的语法仅限C ++。


0
投票

您不能将调用链接到C风格的可变参数函数。唯一的方法是通过va_list作为参数。这正是为什么需要v *系列函数的原因。

因此,您根据va_list编写类似v *的函数,然后将每个函数包装在基于省略号的可变参数函数中。

© www.soinside.com 2019 - 2024. All rights reserved.