【问题标题】:Incorrect function call with variable parameters带可变参数的函数调用不正确
【发布时间】:2020-06-05 09:40:29
【问题描述】:

我正在尝试使用可变数量的参数进行嵌套函数调用,而不检索它们。我得到了错误的结果。

这是我的简单 c++ 程序:

extern "C" {
#include <stdio.h>
}
#include <cstdarg>

class ctty {
    public:
        ctty();
        int logger(int prior, const char* format, ...);
    private:
};

ctty::ctty(){};

int ctty::logger(int prior, const char* format, ...)
{
    va_list ap;
    va_start(ap,format);
    printf(format, ap);
    va_end(ap);
    return 0;
}

int main(int argc, char** argv)
{
    ctty tty;
    tty.logger(0, "Test %d %d %d\n", 7, 5, 5);
    return 0;
}

结果:

Test -205200 7 5

我期待一个结果

Test 7 5 5

我不明白我做错了什么? 提前致谢。

【问题讨论】:

  • 请提供更详细的信息,说明您的期望和结果的差异。别人的代码很难读懂,很多类型和功能都不清楚
  • 是什么让您认为可以将va_list 传递给printf?看看en.cppreference.com/w/cpp/io/c/vfprintf
  • extern "C" { } 围绕标准库包含显然是错误的。我怀疑这是否合法。

标签: c++ function call


【解决方案1】:

您不能直接将va_list 传递给printfva_list 是实际参数列表的包装器(无论其表示形式是什么)。尽管 C 的做法应该是使用 vprintf,但在 C++ 中有更安全的替代方案,例如允许创建更安全的格式化打印版本的可变参数模板,例如(为了简洁起见,一个虚构的格式字符串):

#include <iostream>
#include <cstdlib>

class ctty {
    public:
        ctty();

        template<typename T, typename... Args>
        int logger(int prior, const char* format, T value, Args... args);
    private:
        void logger(int prior, const char *s);
};

ctty::ctty(){};

void ctty::logger(int prior, const char *s)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                throw std::runtime_error("invalid format string: missing arguments");
            }
        }
        std::cout << *s++;
    }
}

template<typename T, typename... Args>
int ctty::logger(int prior, const char* format, T value, Args... args)
{
    while (*format) {
        if (*format == '%') {
                std::cout << value;
                logger(prior, format + 1, args...); 
                return 0;
            }
        std::cout << *format++;
    }
    throw std::logic_error("extra arguments provided to logger");
}

int main(int argc, char** argv)
{
    ctty tty;
    tty.logger(0, "Test % % %\n", 7.55f, "Tada!", 888);
    return 0;
} 

这部分代码:

extern "C" {
#include <stdio.h>
}

从技术上讲,这是一种未定义的行为,虽然它可以编译并且在某些情况下不会产生不利影响,但它不是可移植的。您必须使用 C++ 标头,例如&lt;cstdio&gt;

【讨论】:

    猜你喜欢
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 2016-03-31
    • 2021-11-30
    • 1970-01-01
    相关资源
    最近更新 更多