У меня вопрос по поводу перезапуска списков аргументов с переменным числом аргументов (va_list
).
В основном я хочу сделать что-то вроде этого:
void someFunc(char* fmt, ...) {
va_list ap;
va_start(fmt, ap);
otherFuncA(fmt, ap);
// restart ap
otherFuncB(fmt, ap);
// restart ap
...
va_end(ap);
return;
}
Теперь мой вопрос: как перезагрузить ap
?
Обратите внимание, что этот вопрос относится не к C ++, а к C.
До сих пор я нашел два возможных решения, но мне хотелось бы знать, какое из них "правильное" или "наилучшая практика".
Решение 1: несколько va_start()
С GCC7 я могу заменить строки
// restart ap
в приведенном выше примере
va_end(ap);
va_start(fmt, ap);
для сброса ap
к первому аргументу.
Однако я не уверен, является ли это действительно допустимым кодом, или мне просто повезло, что какое-то неопределенное поведение не повредило результат.
Решение 2: va_copy()
Другое решение, которое отлично работает с GCC7, - инициализация нескольких копий ap
с использованием va_copy()
, например
void someFunc(char* fmt, ...) {
va_list ap1, ap2;
va_start(fmt, ap1);
va_copy(ap2, ap1);
otherFuncA(fmt, ap1);
otherFuncB(fmt, ap2);
va_end(ap1);
va_end(ap2);
return;
}
Это действительный код (imo), но поскольку сейчас существует несколько va_list
экземпляров, которые необходимо скопировать, это гораздо менее эффективно, чем первое решение.
Так какое решение лучше? Это одна из двух, о которых я говорил выше, или что-то совершенно другое?