Ошибка списка аргументов переменной длины - PullRequest
0 голосов
/ 28 июня 2018

много лет назад я написал пользовательскую функцию печати, объявленную так:

void my_printf(char *format_string, ... )
{
    // too complex to list here
}

и я мог бы назвать это так:

my_printf("Number of apples = %d\n",apple);

Эта функция всегда работала идеально. Теперь я хочу создать функцию-оболочку, которая в начале получает дополнительное целое число, например:

void my_printf_extra(int extra,char *format_string, ...)

это можно назвать так:

my_printf_extra(debug_level,"Number of apples = %d\n",apple);

и я бы хотел, чтобы функция-обертка вызывала оригинал примерно так:

void my_printf_extra(int extra,char *format_string, ... )
{
    if (extra == some_test)
    {
        my_printf(** not quite sure what goes here **);
    }
}

Мое предположение было таким:

void my_printf_extra(int extra,char *format_string, ... )
{
    va_list vptr;

    if (extra == some_test)
    {
        va_start(vptr,format_string);
        my_printf(format_string,vptr);
        va_end(vptr);
    }
}

но это не работает. В моем конечном выводе я вижу

Number of apples = -46467968

или какое-то такое число мусора (когда истинное значение было 1). Я вижу похожий мусор при вызове my_printf_extra со строкой. Я подозреваю, что моя обработка va_list неверна, но я не могу понять, как именно.

РЕДАКТИРОВАТЬ: my_printf () является очень гибким и может печатать в самых разных местах. Иногда он просто добавляет текст в окно rich-edit-control-window. Все зависит от разных флагов, а также от содержимого того, что печатается.

1 Ответ

0 голосов
/ 28 июня 2018

Поскольку my_printf не ожидает va_list, вы не можете передать его ему.

Это тот случай, когда использование макроса имеет смысл:

#define my_printf_extra(extra, format_string, ... ) \
do {\
    if ((extra) == some_test)\
    {\
        my_printf((format_string), __VA_ARGS__);\
    }\
} while (0)

Макрос __VA_ARGS__ заменяет все дополнительные параметры. Обратите внимание, что для этого требуется компилятор, который поддерживает C99.

Кроме того, вы можете изменить my_printf для добавления дополнительной логики, изменить имя на что-то внутреннее, а затем определить my_printf и my_printf_extra как макросы, которые вызывают внутреннюю функцию:

void my_printf_impl(int extra, char *format_string, ... )
{
    if (extra != some_test) {
        return;
    }

    ...
}

#define EXTRA_DEFAULT 0
#define my_printf(format_string, ...) \
    my_printf_impl(EXTRA_DEFAULT, format_string, __VA_ARGS__)
#define my_printf_extra(extra, format_string, ...) \
    my_printf_impl(extra, format_string, __VA_ARGS__)
...