2015-07-30 4 views
3

У меня есть следующий код:Как добавить аргумент в va_list

int __dmasprintf (char **s, const char *format, ...) { 

    char buf[512]; 
    va_list arg; 
    int ret; 
    va_start(arg,format); 
    ret = vsprintf(buf, format, arg); 
    va_end(arg); 

    *s = strdup(buf); 
    if (*s == NULL) return -1; 
    return 0; 
} 

Я хочу, чтобы добавить аргумент в va_listarg перед вызовом vsprintf(), потому что мой format содержит 1 дополнительный аргумент в конце.

Как добавить аргумент (например, char * myarg) в va_listarg?

Или можно передать vsprintf() индивидуальный список?

+1

Это макросы. Вы не можете изменить список. – Olaf

+0

@Olaf Можно ли перейти к vsprintf настроенному списку? – MOHAMED

+0

Является ли ваш код скомпилирован компилятором [tag: c] или [tag: C++], или он должен работать в обоих? – Yakk

ответ

1

К сожалению, для этого нет прямого способа. Для этого есть причина: макросы stdarg берут адрес в стек последнего известного параметра, а затем прямо перебирают стек.

Если вы можете использовать макросы, @Useless предоставила хорошее решение - будьте осторожны, макросы могут иметь побочные эффекты, когда вы передаете переменные, предварительно или фиксированные с ++ или --.

Если вы хотите избежать макросов, вам придется написать свой собственный вариант vsprintf. Нет проблем для этого, просто найти источник для C stdlib (GNU libc может быть приятной стартовой точкой) и быть храбрым ... надеюсь, что вы можете использовать макросы!

5

Вы не можете.

Вам необходимо либо сделать два vsprintf вызовов, или заменить функцию с VARIADIC макрокоманды, как

#define __dmasprintf(S, FMT, ...) (\ 
    (*S = do_dmasprintf(FMT, __VA_ARGS__, my_arg)) == NULL ? -1 : 0) 

char *do__dmasprintf (const char *format, ...) { 

    char buf[512]; 
    va_list arg; 
    int ret; 
    va_start(arg,format); 
    ret = vsnprintf(buf, sizeof(buf), format, arg); 
    va_end(arg); 

    char *s = strdup(buf); 
    return s; 
} 

Notes (конечно vsnprintf?):

  1. я заменил vsprintf с vsnprintf , Нет причин использовать здесь здесь (или почти где-нибудь еще)
  2. вы игнорируете ret. Тебе следует?
  3. Я сохранил макет аргумента макроса, аналогичный оригиналу, но поскольку __VA_ARGS__ должен быть одним или несколькими аргументами (он не может быть пустым), это означает, что после FMT требуется хотя бы один аргумент. Просто удалите аргумент FMT целиком, если вы хотите разрешить нулевые аргументы после него.
+0

"он не может быть пустым «правда, хотя GCC допускает его как расширение – newacct

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