开发者

__cdecl Parameter "..." and __VA_ARGS__

#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 */);
}

There were many codes which call foo function in my project.

I made a new macro boo today. And I want to call the macro in foo function.

How can I do this?

Edit:

Of course, we can solve this problem to call some functions(Not macro) like StringCbVPrintf.

But I'm finding a way to call a macro.


An answer that was deemed unhelpful

The question was not properly explained. This answer didn't answer the question that the questioner had in mind, but did answer the question that seemed to be asked. There was a gap between intention and reality.

#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);
}

All facetiousness apart, you call a function or macro with the arguments needed to get your job done. Since you don't specify what the format should be formatted like, I've made up format strings to suit myself - they probably aren't very usable, but who knows.

Anyway, the key point is that you can call boo() the macro with different lists of arguments, and those arguments will be conveyed to SomethingToDo().


An answer that was deemed more helpful

Given the clarification in the comment, then:

#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);
    }
}

However, for that to work, the underlying function needs to know how to handle a va_list. That means you normally end up with the following code with a structure similar to the following:

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);
    }
}

This is a 'standard pattern' for code that uses variable arguments. You can see it in standard C with: printf() and vprintf(); snprintf() and vsnprintf(); fprintf() and vfprintf(); and so on. One version of the function has an ellipsis in the argument list; the other version is prefixed with the letter 'v' and takes a 'va_list' in place of the ellipsis. The ellipsis code is standardized to four or five lines - more or less as shown; it creates and initializes va_list with va_start, calls the v-function, and returns the result after doing va_end.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜