4

In the program below, the variadic function process_message passes its variable arguments via the va_list argp parameter to print_message. argp is in turn passed to vsnprintf which calculates the length of the format string.

However, if argp is passed to a another function called from within print_message such as vprintf(fmt, argp), it produces nonsense output. Is it possible for a function taking va_list parameter to use it more than once?

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

1 Answer 1

8

You can use va_copy:

The va_copy() macro copies the (previously initialized) variable argument list src to dest. The behavior is as if va_start() were applied to dest with the same last argument, followed by the same number of va_arg() invocations that was used to reach the current state of src.

You print_message() could be:

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

NOTE:

Don't forget to call va_end after using a copied va_list.

C11:

Each invocation of the va_start and va_copy macros shall be matched by a corresponding invocation of the va_end macro in the same function.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.