C使用va_list的函数可以多次使用它吗?

use*_*803 3 c variadic-functions

在下面的程序中,可变参数函数process_message通过va_list argp参数to 传递其变量参数print_message.argp反过来传递给vsnprintf计算格式字符串的长度.

然而,如果argp被传递给从内调用另一个函数print_message,例如vprintf(fmt, argp),它产生无义输出.函数va_list参数可以多次使用吗?

#include <stdio.h>
#include <stdarg.h>

void process_message(const char *fmt, ...);
void print_message(const char *fmt, va_list argp);

int main(void) {
  process_message("%s:%d\n", "test message", 1);
  return 0;
}

void process_message(const char *fmt, ...) {
  va_list argp;
  va_start(argp, fmt);
  print_message(fmt, argp);
  va_end(argp);
}

void print_message(const char *fmt, va_list argp) {
  /*Calculate and print the length of the format string*/
  int len = vsnprintf(NULL, 0, fmt, argp);
  printf("Length of format string = %d\n", len);
  /*Print the rendered format string - this produces a nonsense output
   *if argp was aleady passed to another function earlier */
  vprintf(fmt, argp);
}
Run Code Online (Sandbox Code Playgroud)

lll*_*lll 7

你可以使用va_copy:

va_copy()宏将(先前初始化的)变量参数列表src复制到dest.行为就好像va_start()应用于具有相同最后一个参数的dest,然后是用于达到src当前状态的相同数量的va_arg()调用.

print_message()可能是:

void print_message(const char *fmt, va_list argp) {
  /*Calculate and print the length of the format string*/ 
  va_list argp_copy;
  va_copy(argp_copy, argp);
  int len = vsnprintf(NULL, 0, fmt, argp_copy);
  va_end(argp_copy);

  printf("Length of format string = %d\n", len);
  /*Print the rendered format string - this produces a nonsense output
   *if argp was aleady passed to another function earlier */
  vprintf(fmt, argp);
}
Run Code Online (Sandbox Code Playgroud)

注意:

va_end使用复制后不要忘记打电话va_list.

C11:

va_start和va_copy宏的每次调用都应与相同函数中va_end宏的相应调用相匹配.