Вы не можете. Для того, чтобы создать va_list
, вам понадобится функция Variadi c. Не существует переносимого средства для создания объекта va_list
из списка аргументов.
Довольно часто функции Variadi c пишутся парами: внешняя функция использует средства в <stdarg.h>
для построения a va_list
, и он передает этот список непосредственно функции, которая выполняет эту работу. Вы видите, что в стандартной библиотеке ввода-вывода, например: printf
/ vprintf
, fprintf
/ vfprintf
, snprintf
/ vsnprintf
, scanf
/ vscanf
, et c .
И вот что вы должны сделать для своей проблемы: запишите exampleB
как va_list
форму exampleA
.
Вот, например, полная реализация fprintf
извлечена из библиотеки FreeBSD, которая может служить моделью этого стиля:
int
fprintf(FILE * __restrict fp, const char * __restrict fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vfprintf_l(fp, __get_locale(), fmt, ap);
va_end(ap);
return (ret);
}
Как видно из этого фрагмента, vfprintf_l
(который принимает аргумент локали) на самом деле является реализацией ; все остальные *printf
функции являются простыми оболочками. (printf
, например, вызывает vfprintf_l
с передачей stdin
и аргумента языкового стандарта.) Это позволяет избежать обхода нескольких оболочек за один вызов, хотя современные оптимизирующие компиляторы обычно могут выполнять это исключение автоматически.
(См. lib / libc / stdio / fprintf. c для полного файла в зеркале исходного репозитория FreeBSD на Github.)
Говоря о переносимости, #define exampleA(buf, args...)
- это расширение G CC, которое не переносимо для большинства реализаций C (хотя Clang также реализует его). Вы должны использовать __VA_ARGS__
в соответствии со стандартом C:
#define exampleA(buf, ...) \
exampleB(buf, ## __VA_ARGS__)
Еще лучше, если вы можете, заменить другое расширение G CC (, ##
) на более новый стандарт __VA_OPT__
:
#define exampleA(buf, ...) \
exampleB(buf __VA_OPT__(,) __VA_ARGS__)