代码之家  ›  专栏  ›  技术社区  ›  Benjamin

__cdecl参数“…”和u VA_ARGS__

  •  2
  • Benjamin  · 技术社区  · 15 年前
    #define boo(fmt, ...)   SomethingToDo(fmt, __VA_ARGS__)
    void foo(PCSTR fmt, ...)
    {
        // some other codes
        if(condition1)
        {
            va_list marker;
            va_start(maker, fmt);
            // Do something.
            va_end(marker);
        }
    
        if(somecondition)
            boo(fmt, /* I want to put the foo's va_arguments here */);
    }
    


    我今天做了一个新的宏boo。我想调用foo函数中的宏。

    我该怎么做?

    编辑:
    当然,我们可以通过调用一些函数(不是宏)来解决这个问题,比如StringCbVPrintf。
    但我正在想办法调用宏。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Jonathan Leffler    15 年前

    被认为毫无帮助的回答

    这个问题没有得到恰当的解释。这个答案并没有回答提问者心中的问题,而是回答了似乎要问的问题。意图和现实之间有差距。

    #define boo(fmt, ...) SomethingToDo(fmt, __VA_ARGS__) // semi-colon removed!
    void foo(PCSTR fmt, ...)
    {
        // some other codes
    
        // I want to call boo with VarArgs.
        if (somecondition)
            boo(fmt, arg1, arg2);
        if (anothercondition)
            boo("%x %y %z", e1, e2, e3);
        if (yetanothercondition)
            boo("&T99 P37 T22 9%X  ZZQ", x1, y2, z3, a4, b9, c7, q99);
    }
    

    除了开玩笑之外,你调用一个函数或宏,其中包含完成工作所需的参数。因为您没有指定格式应该是什么样的,所以我编写了适合自己的格式字符串—它们可能不是很有用,但谁知道呢。

    boo() 宏包含不同的参数列表,这些参数将传递给 SomethingToDo() .


    一个被认为更有帮助的答案

    #define boo(fmt, ...)   SomethingToDo(fmt, __VA_ARGS__)
    void foo(PCSTR fmt, ...)
    {
        va_list args;
    
        // I want to call boo with VarArgs.
        if (somecondition)
        {
            va_start(args, fmt);
            boo(fmt, args);
            va_end(args);
        }
    }
    

    但是,要使其工作,底层函数需要知道如何处理 va_list

    void vSomethingToDo(const char *fmt, va_list args)
    {
        ...code using vfprintf() or whatever...
    }
    
    void SomethingToDo(const char *fmt, ...)
    {
        va_list args;
        va_start(args, fmt);
        vSomethingToDo(fmt, args);
        va_end(args);
    }
    
    #define vboo(fmt, args) vSomethingToDo(fmt, args)
    #define boo(fmt, ...)    SomethingToDo(fmt, __VA_ARGS__)
    
    void foo(PCSTR fmt, ...)
    {
        ...other code...
        if (somecondition)
        {
            va_list args;
            va_start(args, fmt);
            vboo(fmt, args);
            va_end(args);
        }
    }
    

    这是使用变量参数的代码的“标准模式”。您可以在标准C中看到: printf() vprintf() ; snprintf() vsnprintf() fprintf() vfprintf() ;等等。函数的一个版本在参数列表中有省略号;另一个版本以字母“v”作为前缀,并使用“va\u list”代替省略号。省略号代码被标准化为四行或五行(或多或少如图所示);它创建并初始化带有va\u start的va\u列表,调用v函数,并在执行va\u end之后返回结果。