如何向 va_list 添加参数

How to add an argument to a 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;   
}

我想在调用 vsprintf() 之前向 va_list arg 添加一个参数,因为我的 format 在末尾包含 1 个额外的参数。

如何向 va_list arg 添加参数(例如 char * myarg)?

或者是否可以传递 vsprintf() 自定义列表?

你不能。

您要么需要进行两次 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. 我用 vsnprintf 替换了 vsprintf。没有理由在这里(或几乎任何其他地方)使用前者
  2. 你忽略ret。你应该吗?
  3. 我保持宏参数布局与原来的类似,但由于 __VA_ARGS__ 必须是一个或多个参数(不能为空),这意味着在 [ 之后至少需要一个参数=17=]。如果你想在它后面允许零参数,只需完全删除 FMT 参数。

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

如果你可以使用宏,@Useless 提供了一个很好的解决方案 - 请注意,当你传递变量时,宏可能会产生副作用 - 或 post - 固定为 ++--.

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