如何将参数添加到va_list

时间:2015-07-30 14:00:21

标签: c variadic-functions

我有以下代码:

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_list之前向arg vsprintf()添加一个参数,因为我的format最后包含1个额外的参数。

如何将参数(例如char * myarg)添加到va_list arg

或者是否可以通过vsprintf()自定义列表?

2 个答案:

答案 0 :(得分:5)

你不能。

您需要制作两个vsprintf(肯定是 vsnprintf ?)调用,或者使用可变参数宏替换您的函数,例如

#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;   
}

注意:

  1. 我将vsprintf替换为vsnprintf。没有理由在这里使用前者(或其他任何地方)
  2. 你忽略了ret。你呢?
  3. 我保持宏参数布局类似于原始布局,但由于__VA_ARGS__必须是一个或多个参数(它不能为空),这意味着{{1}后需要至少一个参数}}。如果要在其后允许零参数,则完全删除FMT参数。

答案 1 :(得分:1)

遗憾的是,没有直接的方法可以做到这一点。有一个原因:stdarg宏获取最后一个已知参数的堆栈中的地址,然后直接迭代堆栈。

如果您可以使用宏,@ Useless提供了一个很好的解决方案 - 请注意,当您使用++--预先或后修复变量时,宏可能会产生副作用。

如果您想避免使用宏,则必须编写自己的vsprintf变体。没问题,只需找到C stdlib的源代码(GNU libc可能是个不错的起点)并且勇敢...希望你能使用宏!