Подтвердить что ты не робот

Как использовать __VA_ARGS__ внутри функции C вместо макроса?

Возможный дубликат:
C/С++: передача переменной количества аргументов вокруг

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

#define COMMON_Print(...) printf (__VA_ARGS__)

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

void COMMON_Print(...)
{    
    printf (__VA_ARGS__);
}

Так что функция не работает, я получаю сообщение об ошибке

"Ошибка: undefined идентификатор __VA_ARGS __"

Сложность моего проекта требует наличия функции, так как это интерфейс... Так как я могу получить параметры... и передать их функции printf? Или лучше, что я делаю неправильно?

Спасибо!

4b9b3361

Ответ 1

Каждая из функций ?printf имеет соответствующую функцию v?printf, которая делает то же самое, но принимает va_list, список переменных аргументов.

#include <stdio.h>
#include <stdarg.h>

void COMMON_Print(char *format, ...)
{
    va_list args;

    va_start(args, format);
    vprintf(format, args);
    va_end(args);
}

Примечание: Обратите внимание, что va_start принимает имя последнего аргумента перед ... в качестве параметра. va_start - это макрос, который делает некоторую магию стека для получения аргументов переменной и для этого нужен адрес последнего фиксированного аргумента.

В результате этого должен быть хотя бы один фиксированный аргумент, поэтому вы можете передать его в va_start. Вот почему я добавил аргумент format вместо того, чтобы придерживаться более простого объявления COMMON_Print(...).

Смотрите: http://www.cplusplus.com/reference/clibrary/cstdio/vprintf/

Ответ 2

__VA_ARGS__ предназначен только для макросов; вариационные функции довольно разные. Вам нужно использовать va_start, va_arg и va_end из stdarg.h для их обработки.

Во-первых, вашей функции требуется хотя бы один именованный параметр, например:

void COMMON_Print(const char* fmt, ...)

Затем вы можете определить va_list и использовать va_start для его установки:

va_list args;
va_start(args, fmt);
// your code here
va_end(args);

Теперь вы можете использовать args для доступа к аргументам; вызов va_arg(args, TYPE) вернет следующий переменный аргумент, поэтому вы можете просто продолжать называть это, пока не прочитаете все аргументы.

Если вы просто пытаетесь вызвать printf, есть вариант printf, называемый vprintf, который принимает непосредственно va_list:

vprintf(fmt, args);

Нет простого способа вызвать одну переменную функцию из другой; вам нужно что-то вроде vprintf, которое принимает целое va_list

Ответ 3

__VA_ARGS__ предназначен только для макросов.

Связывание переменной числа аргументов с другой функцией не может быть выполнено напрямую. Вместо этого вы должны передайте va_list, и функция, которую вы вызываете, должна взять va_list. К счастью, есть вариант printf, который делает это, ваша функция должна быть написана следующим образом:

void COMMON_Print(char *format,...)
{    
  va_list args;
  va_begin(args,format);
  vsprintf(format,args);
  va_end(args);
}

Ответ 4

Что вы ищете, это Ellipsis.