【问题标题】:Variadic function does not pass the first argument correctly可变参数函数未正确传递第一个参数
【发布时间】:2019-04-12 00:25:30
【问题描述】:

我使用了可变参数函数来包装printf(或vprintf)。

除了在warning_printf 的第一个可变参数上出错之外,以下代码有效。此外,直接放置字符串会改变 ASCII 字符,但它并不能修复它,因为消息仍然是随机的。

它打印的是什么

[Warning]
          ®¯$ address: 0x87afae8a

代替

[Warning] Failed to initialize setting address: 0x87afae8a

“警告”一词的颜色正确(无论如何都无关紧要)。但是msg_warn 似乎没有正确传递。我测试了向这个函数添加更多变量。除了第一个可变参数msg_warn之外,它们都可以正常工作。

我的代码有什么问题?

void colorful_printf( const char* header, const char* color, const char* fmt, ... )
{
    printf("[%s%s%s] ", color, header, RESET_ANSI_COLOR);
    va_list args;
    va_start( args, fmt );
    vprintf(fmt, args);
    va_end( args );
}


void warning_printf( const char* fmt, ... )
{
    va_list args;
    va_start( args, fmt );
    colorful_printf("Warning", WARNING_COLOR, fmt, args);
    va_end( args );
}


char msg_warn[] = "Failed to initialize setting";
warning_printf( "%s address: 0x%2x", msg_warn, address );

在线编译器:link

【问题讨论】:

  • 您需要一个采用va_list 而不是... 的函数。
  • @JonathanLeffler,通过复制还是通过引用?
  • 复制。我认为Repeated use of a variadic function argument doesn't work 有相关材料,但我也认为我写了一个更相关的答案——我就是找不到。有时,写下答案比找到正确的问答更容易。
  • Th 问题 Passing variable arguments to another function that accepts a variable argument list 被标记为 C++,但答案同样适用于 C。它涵盖了与我在下面的答案相同的领域 — 您创建的函数采用 va_list 而不是 @987654335 @ 和 ... 函数创建一个 va_list,然后调用采用 va_list 的函数来完成实际工作。尽管 C++ 和 C 不匹配,但我们需要就它是否可以作为副本达成共识,或者考虑将其重新标记为 C++ C(哎呀!)。

标签: c printing variadic-functions


【解决方案1】:

您需要将va_list 传递给期望它们的函数——类似于v*printf() 函数。

void colorful_vprintf(const char* header, const char* color, const char* fmt, va_list args)
{
    printf("[%s%s%s] ", color, header, RESET_ANSI_COLOR);
    vprintf(fmt, args);
}

void colorful_printf(const char* header, const char* color, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    colorful_vprintf(header, color, fmt, args);
    va_end(args);
}

void warning_vprintf(const char* fmt, va_list args)
{
    colorful_vprintf("Warning", WARNING_COLOR, fmt, args);
}

void warning_printf(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    warning_vprintf(fmt, args);
    va_end(args);
}

*_vprintf 函数做真正的工作;具有省略号的函数只需获取参数的va_list 并将它们传递给*_vprintf() 函数。 这是printf() 系列函数的接口(包装器)的一般模式。

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多