vprintf是如何实现的?

Tob*_*ull 1 c variadic-functions

如果想在C中编写一个函数,将一个变量参数列表传递给printf一个必须使用该vprintf版本的函数.如何为自定义函数实现此机制?

换句话说,如何是什么套的精髓vprintf除了printf在符合标准的C语言实现?

ric*_*ici 6

如果你想编写一个va_list以参数形式作为参数的vprintf函数,那么你就是这样做的.您可以以正常方式从va_listwith va_arg中提取参数.

不要打电话va_start或va_end上va_list:这是调用者的责任.由于您无法va_list以正常方式重新启动,如果您需要多次扫描,您将需要va_copy它.

这是一个简单的例子,仅用于说明(即它并不意味着是最好的实现).

这两个函数只是使用提供的分隔符字符串连接一堆字符串.第一个是"v"版本(如vsprintf),它实现了逻辑.第二个是varargs版本,它打包va_list并将其传递给实现.

内部函数遍历参数两次; 第一次添加字符串的大小.这两个函数都返回一个新的malloc字符串,该字符串需要被调用者释放.

参数列表必须以a结尾NULL.

char* vjoin(const char* delim, va_list ap) {
  va_list aq;
  va_copy(aq, ap);
  size_t dlen = strlen(delim);

  /* First pass. Use the copied va_list */
  size_t needed = 1; /* NUL terminator */
  const char* s = va_arg(aq, const char*);
  if (s) {
    needed += strlen(s);
    while ((s = va_arg(aq, const char*)))
      needed += dlen + strlen(s);
  }
  va_end(aq);

  /* Second pass. Use the original va_list */
  char* rv = malloc(needed);
  size_t offset = 0;
  *rv = 0;
  s = va_arg(ap, const char*);
  if (s) {
    strcpy(rv, s);
    offset = strlen(s);
    while ((s = va_arg(ap, const char*))) {
      strcpy(rv + offset, delim);
      strcpy(rv + offset + dlen, s);
      offset += dlen + strlen(s);
    }
  }
  return rv;
}

char* join(const char* delim, ...) {
  va_list ap;
  va_start(ap, delim);
  char* rv = vjoin(delim, ap);
  va_end(ap);
  return rv;
}
Run Code Online (Sandbox Code Playgroud)