Передать va_list или указатель на va_list? - PullRequest
20 голосов
/ 30 июля 2010

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

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

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

Ответы [ 5 ]

25 голосов
/ 30 июля 2010

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

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

[мой курсив]

Редактировать: Только что заметил стандарт в сноске:

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

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

2 голосов
/ 30 июля 2010

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

2 голосов
/ 30 июля 2010

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

"va_list сам по себе не является списком переменных аргументов, это действительно своего рода указатель на один из них.функция, которая принимает va_list, сама по себе не является ни varargs, ни наоборот. "

0 голосов
/ 15 июня 2011

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

0 голосов
/ 30 июля 2010

Функции в стандартной библиотеке 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...