2010-07-30 16 views
17

Предположим, что у меня есть функция, которая принимает вариативные аргументы (...) или va_list, переданные из другой такой функции. Основная логика заключается в самой этой функции (назовем ее f1), но я хочу, чтобы она передала va_list другой функции (назовем ее f2), которая определит следующий тип аргумента, получит ее с помощью va_arg и правильно преобразует и сохраните его для использования вызывающим абонентом.Пропустить va_list или указатель на va_list?

Достаточно ли передать va_list в f2 или необходимо передать указатель на va_list. Если va_list не требуется, чтобы быть типом массива или хранить его данные позиции в том месте, на котором объект va_list указывает (а не на сам объект), я не вижу, как передача его по значению может позволить вызывающую функцию (f1) «видеть» изменения вызванной функции, сделанные va_arg.

Может ли кто-нибудь пролить свет на это? Меня интересует то, что требует стандарт, а не то, что позволяет определенная реализация.

ответ

23

Похоже, что вам нужно будет передать указатель на va_list. Для получения дополнительной информации, смотрите раздел 7.15.In частности, пуля точка 3 состояний C99 standard document:

Объект ар может быть передан в качестве аргумента другой функции; если эта функция вызывает va_arg макрос с параметром ар, значение ар в вызывающей функции неопределенна и должны быть переданы в va_end макро до каких-либо дальнейших ссылок на ар

[курсив мой]

Edit: Просто заметил сноску в стандарте:

215) разрешается создать указатель на va_list и передать этот указатель другая функция, в которой случае исходная функция может сделать дальнейшее использование исходного списка после того, как другой функции возвращает

Таким образом, вы можете передать указатель на va_list и делать va_arg(*va_list_pointer) в вызываемой функции.

+0

Согласовано с последним правлением - указатель - это путь (поскольку OP хочет, чтобы изменения в 'va_list' были определенно видны в вызывающей функции). – caf

+0

@caf: Я не думаю, что вы должны были отредактировать мою ссылку на 'vfprintf()', потому что похоже, что другие совершают ту же ошибку, что и я, и предлагают испытуемому взглянуть на существующие прототипы (что на самом деле не ответить на его вопрос). – JeremyP

+2

Я бы сказал, оставить комментарий и/или проголосовать за них тогда - кажется, лучше иметь правильный ответ, который не был бы запутан с более ранним, неправильным допущением ... – caf

2

В моем понимании вы должны передать va_list напрямую (а не указатель на него). Это, кажется, поддерживается comp.lang.c:.

«А va_list не сама переменная список аргументов, это действительно своего рода указатель на один То есть функция, которая принимает va_list не сам с переменным числом аргументов, ни вице- versa. "

+0

Я не думаю, что цитата поддерживает ваше утверждение. Ничто об этом не запрещает передачу указателя на 'va_list', и действительно стандарт явно говорит, что это разрешено. – caf

2

Я нахожу тексты довольно двусмысленными по этому вопросу. Самое простое - это, возможно, посмотреть в стандарте, как предполагается, что его предопределенные функции с va_list принимают, например vsnprintf. И это явно по стоимости, а не по ссылке.

+1

Стандартные функции не предназначены для вызова так, как OP хочет - после их вызова 'va_list' больше не может использоваться и должен передаваться только в' va_end() '. – caf

+0

Действительно, я OP, и я согласен с кафе на этом. JeremyP является единственным, кто, кажется, привел какие-либо доказательства, и стандарт довольно ясен, что вам нужно передать указатель на семантику, которую я хочу. –

0

Функции стандартной библиотеки C проход va_list сам элемент (man 3 vprintf):

#include <stdarg.h> 

    int vprintf(const char *format, va_list ap); 
    int vfprintf(FILE *stream, const char *format, va_list ap); 
    int vsprintf(char *str, const char *format, va_list ap); 
    int vsnprintf(char *str, size_t size, const char *format, va_list ap); 
+1

Ни одна из этих функций не предназначена для вызова так, как хочет OP - после вызова этих функций 'va_list' больше не может использоваться и должен передаваться только в' va_end() '. – caf

0

Попутный указатель va_list отлично работает в 32-битной системе. Вы даже можете выбрать один параметр в подпрограмме. Но он, похоже, не работает в 64-битной системе, приведет к возникновению ошибки сегмента в va_arg().

Смежные вопросы