__cdecl Параметр "..." и __VA_ARGS__ - PullRequest
2 голосов
/ 31 августа 2010
#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 */);
}

В моем проекте было много кодов, вызывающих функцию foo.
Я сделал новый макрос бу сегодня. И я хочу вызвать макрос в функции foo.

Как я могу это сделать?

Edit:
Конечно, мы можем решить эту проблему для вызова некоторых функций (не макросов), таких как StringCbVPrintf.
Но я нахожу способ вызвать макрос.

1 Ответ

1 голос
/ 31 августа 2010

Ответ, который был признан бесполезным

Вопрос не был правильно объяснен. Этот ответ не ответил на вопрос, который имел в виду спрашивающий, но ответил на вопрос, который, казалось, был задан. Между намерением и реальностью был разрыв.

#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_list». Код многоточия стандартизирован в четыре или пять строк - более или менее, как показано; он создает и инициализирует va_list с помощью va_start, вызывает функцию v и возвращает результат после выполнения va_end.

...