Как использовать __VA_ARGS__ внутри функции C вместо макроса?
Возможный дубликат:
C/С++: передача переменной количества аргументов вокруг
В настоящее время я использую следующий макрос, объявленный в моем файле C.
#define COMMON_Print(...) printf (__VA_ARGS__)
Теперь этот вызов работает нормально, но получается, что мне нужно создать C-функцию, которая выглядит примерно так:
void COMMON_Print(...)
{
printf (__VA_ARGS__);
}
Так что функция не работает, я получаю сообщение об ошибке
"Ошибка: undefined идентификатор __VA_ARGS __"
Сложность моего проекта требует наличия функции, так как это интерфейс... Так как я могу получить параметры... и передать их функции printf? Или лучше, что я делаю неправильно?
Спасибо!
Ответы
Ответ 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.