【问题标题】:call printf using va_list使用 va_list 调用 printf
【发布时间】:2011-08-24 01:19:30
【问题描述】:
void TestPrint(char* format, ...)
{
    va_list argList;

    va_start(argList, format);
    printf(format, argList);
    va_end(argList);
}


int main()
{
    TestPrint("Test print %s %d\n", "string", 55);
    return 0;
}

我需要得到:

Test print string 55

实际上,我得到了垃圾输出。这段代码有什么问题?

【问题讨论】:

    标签: c printf variadic-functions


    【解决方案1】:

    请改用vprintf()

    【讨论】:

    • @PingwinTux:是的。这种回应在 2011 年是可以接受的;)
    • 是的,现在人们希望他们的手被握住。可能也是一种更好、更具教学性的方式,并且对新手更友好(在 StackOverflow 和一般编程中)。
    【解决方案2】:

    我建议您尝试使用 vprintf 而不是 printf,它是为此特定目的而创建的:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    
    void errmsg( const char* format, ... )
    {
        va_list arglist;
    
        printf( "Error: " );
        va_start( arglist, format );
        vprintf( format, arglist );
        va_end( arglist );
    }
    
    int main( void )
    {
        errmsg( "%s %d %s", "Failed", 100, "times" );
        return EXIT_SUCCESS;
    }
    

    Source

    【讨论】:

    • 这个例子让我很开心!
    【解决方案3】:

    正如其他人已经指出的那样:在这种情况下,您应该改用vprintf

    但是如果你真的想包装printf,或者想包装一个没有v... 版本的函数,你可以在GCC 中使用非标准的__builtin_apply 功能来做到这一点:

    int myfunction(char *fmt, ...)
    {
        void *arg = __builtin_apply_args();
        void *ret = __builtin_apply((void*)printf, arg, 100);
        __builtin_return(ret);
    }
    

    __builtin_apply 的最后一个参数是最大值。参数的总大小(以字节为单位)。确保在此处使用足够大的值。

    【讨论】:

    • 感谢您的回答,它直接解决了 OP 的问题。出于拦截目的,这段代码救了我的命! (或者至少避免我服从组装:)
    • 这个值可以有最大值吗? __builtin_apply() 应该解析调用堆栈帧以自行找出值。但这取决于架构是否可行以及效果如何。我曾经为自己嫁接了一个类似的解决方案。太可怕了。
    【解决方案4】:

    这不是您使用printf() 的方式。如果您想使用va_lists,请改用vprintf()。参考here

    【讨论】:

      猜你喜欢
      • 2013-03-03
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-19
      • 2019-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多